| File: | build/source/llvm/lib/IR/Verifier.cpp |
| Warning: | line 2822, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===-- Verifier.cpp - Implement the Module Verifier -----------------------==// | ||||
| 2 | // | ||||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||
| 6 | // | ||||
| 7 | //===----------------------------------------------------------------------===// | ||||
| 8 | // | ||||
| 9 | // This file defines the function verifier interface, that can be used for some | ||||
| 10 | // basic correctness checking of input to the system. | ||||
| 11 | // | ||||
| 12 | // Note that this does not provide full `Java style' security and verifications, | ||||
| 13 | // instead it just tries to ensure that code is well-formed. | ||||
| 14 | // | ||||
| 15 | // * Both of a binary operator's parameters are of the same type | ||||
| 16 | // * Verify that the indices of mem access instructions match other operands | ||||
| 17 | // * Verify that arithmetic and other things are only performed on first-class | ||||
| 18 | // types. Verify that shifts & logicals only happen on integrals f.e. | ||||
| 19 | // * All of the constants in a switch statement are of the correct type | ||||
| 20 | // * The code is in valid SSA form | ||||
| 21 | // * It should be illegal to put a label into any other type (like a structure) | ||||
| 22 | // or to return one. [except constant arrays!] | ||||
| 23 | // * Only phi nodes can be self referential: 'add i32 %0, %0 ; <int>:0' is bad | ||||
| 24 | // * PHI nodes must have an entry for each predecessor, with no extras. | ||||
| 25 | // * PHI nodes must be the first thing in a basic block, all grouped together | ||||
| 26 | // * All basic blocks should only end with terminator insts, not contain them | ||||
| 27 | // * The entry node to a function must not have predecessors | ||||
| 28 | // * All Instructions must be embedded into a basic block | ||||
| 29 | // * Functions cannot take a void-typed parameter | ||||
| 30 | // * Verify that a function's argument list agrees with it's declared type. | ||||
| 31 | // * It is illegal to specify a name for a void value. | ||||
| 32 | // * It is illegal to have a internal global value with no initializer | ||||
| 33 | // * It is illegal to have a ret instruction that returns a value that does not | ||||
| 34 | // agree with the function return value type. | ||||
| 35 | // * Function call argument types match the function prototype | ||||
| 36 | // * A landing pad is defined by a landingpad instruction, and can be jumped to | ||||
| 37 | // only by the unwind edge of an invoke instruction. | ||||
| 38 | // * A landingpad instruction must be the first non-PHI instruction in the | ||||
| 39 | // block. | ||||
| 40 | // * Landingpad instructions must be in a function with a personality function. | ||||
| 41 | // * All other things that are tested by asserts spread about the code... | ||||
| 42 | // | ||||
| 43 | //===----------------------------------------------------------------------===// | ||||
| 44 | |||||
| 45 | #include "llvm/IR/Verifier.h" | ||||
| 46 | #include "llvm/ADT/APFloat.h" | ||||
| 47 | #include "llvm/ADT/APInt.h" | ||||
| 48 | #include "llvm/ADT/ArrayRef.h" | ||||
| 49 | #include "llvm/ADT/DenseMap.h" | ||||
| 50 | #include "llvm/ADT/MapVector.h" | ||||
| 51 | #include "llvm/ADT/STLExtras.h" | ||||
| 52 | #include "llvm/ADT/SmallPtrSet.h" | ||||
| 53 | #include "llvm/ADT/SmallSet.h" | ||||
| 54 | #include "llvm/ADT/SmallVector.h" | ||||
| 55 | #include "llvm/ADT/StringExtras.h" | ||||
| 56 | #include "llvm/ADT/StringMap.h" | ||||
| 57 | #include "llvm/ADT/StringRef.h" | ||||
| 58 | #include "llvm/ADT/Twine.h" | ||||
| 59 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
| 60 | #include "llvm/IR/Argument.h" | ||||
| 61 | #include "llvm/IR/Attributes.h" | ||||
| 62 | #include "llvm/IR/BasicBlock.h" | ||||
| 63 | #include "llvm/IR/CFG.h" | ||||
| 64 | #include "llvm/IR/CallingConv.h" | ||||
| 65 | #include "llvm/IR/Comdat.h" | ||||
| 66 | #include "llvm/IR/Constant.h" | ||||
| 67 | #include "llvm/IR/ConstantRange.h" | ||||
| 68 | #include "llvm/IR/Constants.h" | ||||
| 69 | #include "llvm/IR/DataLayout.h" | ||||
| 70 | #include "llvm/IR/DebugInfo.h" | ||||
| 71 | #include "llvm/IR/DebugInfoMetadata.h" | ||||
| 72 | #include "llvm/IR/DebugLoc.h" | ||||
| 73 | #include "llvm/IR/DerivedTypes.h" | ||||
| 74 | #include "llvm/IR/Dominators.h" | ||||
| 75 | #include "llvm/IR/EHPersonalities.h" | ||||
| 76 | #include "llvm/IR/Function.h" | ||||
| 77 | #include "llvm/IR/GCStrategy.h" | ||||
| 78 | #include "llvm/IR/GlobalAlias.h" | ||||
| 79 | #include "llvm/IR/GlobalValue.h" | ||||
| 80 | #include "llvm/IR/GlobalVariable.h" | ||||
| 81 | #include "llvm/IR/InlineAsm.h" | ||||
| 82 | #include "llvm/IR/InstVisitor.h" | ||||
| 83 | #include "llvm/IR/InstrTypes.h" | ||||
| 84 | #include "llvm/IR/Instruction.h" | ||||
| 85 | #include "llvm/IR/Instructions.h" | ||||
| 86 | #include "llvm/IR/IntrinsicInst.h" | ||||
| 87 | #include "llvm/IR/Intrinsics.h" | ||||
| 88 | #include "llvm/IR/IntrinsicsAArch64.h" | ||||
| 89 | #include "llvm/IR/IntrinsicsARM.h" | ||||
| 90 | #include "llvm/IR/IntrinsicsWebAssembly.h" | ||||
| 91 | #include "llvm/IR/LLVMContext.h" | ||||
| 92 | #include "llvm/IR/Metadata.h" | ||||
| 93 | #include "llvm/IR/Module.h" | ||||
| 94 | #include "llvm/IR/ModuleSlotTracker.h" | ||||
| 95 | #include "llvm/IR/PassManager.h" | ||||
| 96 | #include "llvm/IR/Statepoint.h" | ||||
| 97 | #include "llvm/IR/Type.h" | ||||
| 98 | #include "llvm/IR/Use.h" | ||||
| 99 | #include "llvm/IR/User.h" | ||||
| 100 | #include "llvm/IR/Value.h" | ||||
| 101 | #include "llvm/InitializePasses.h" | ||||
| 102 | #include "llvm/Pass.h" | ||||
| 103 | #include "llvm/Support/AtomicOrdering.h" | ||||
| 104 | #include "llvm/Support/Casting.h" | ||||
| 105 | #include "llvm/Support/CommandLine.h" | ||||
| 106 | #include "llvm/Support/ErrorHandling.h" | ||||
| 107 | #include "llvm/Support/MathExtras.h" | ||||
| 108 | #include "llvm/Support/raw_ostream.h" | ||||
| 109 | #include <algorithm> | ||||
| 110 | #include <cassert> | ||||
| 111 | #include <cstdint> | ||||
| 112 | #include <memory> | ||||
| 113 | #include <optional> | ||||
| 114 | #include <string> | ||||
| 115 | #include <utility> | ||||
| 116 | |||||
| 117 | using namespace llvm; | ||||
| 118 | |||||
| 119 | static cl::opt<bool> VerifyNoAliasScopeDomination( | ||||
| 120 | "verify-noalias-scope-decl-dom", cl::Hidden, cl::init(false), | ||||
| 121 | cl::desc("Ensure that llvm.experimental.noalias.scope.decl for identical " | ||||
| 122 | "scopes are not dominating")); | ||||
| 123 | |||||
| 124 | namespace llvm { | ||||
| 125 | |||||
| 126 | struct VerifierSupport { | ||||
| 127 | raw_ostream *OS; | ||||
| 128 | const Module &M; | ||||
| 129 | ModuleSlotTracker MST; | ||||
| 130 | Triple TT; | ||||
| 131 | const DataLayout &DL; | ||||
| 132 | LLVMContext &Context; | ||||
| 133 | |||||
| 134 | /// Track the brokenness of the module while recursively visiting. | ||||
| 135 | bool Broken = false; | ||||
| 136 | /// Broken debug info can be "recovered" from by stripping the debug info. | ||||
| 137 | bool BrokenDebugInfo = false; | ||||
| 138 | /// Whether to treat broken debug info as an error. | ||||
| 139 | bool TreatBrokenDebugInfoAsError = true; | ||||
| 140 | |||||
| 141 | explicit VerifierSupport(raw_ostream *OS, const Module &M) | ||||
| 142 | : OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()), | ||||
| 143 | Context(M.getContext()) {} | ||||
| 144 | |||||
| 145 | private: | ||||
| 146 | void Write(const Module *M) { | ||||
| 147 | *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; | ||||
| 148 | } | ||||
| 149 | |||||
| 150 | void Write(const Value *V) { | ||||
| 151 | if (V) | ||||
| 152 | Write(*V); | ||||
| 153 | } | ||||
| 154 | |||||
| 155 | void Write(const Value &V) { | ||||
| 156 | if (isa<Instruction>(V)) { | ||||
| 157 | V.print(*OS, MST); | ||||
| 158 | *OS << '\n'; | ||||
| 159 | } else { | ||||
| 160 | V.printAsOperand(*OS, true, MST); | ||||
| 161 | *OS << '\n'; | ||||
| 162 | } | ||||
| 163 | } | ||||
| 164 | |||||
| 165 | void Write(const Metadata *MD) { | ||||
| 166 | if (!MD) | ||||
| 167 | return; | ||||
| 168 | MD->print(*OS, MST, &M); | ||||
| 169 | *OS << '\n'; | ||||
| 170 | } | ||||
| 171 | |||||
| 172 | template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { | ||||
| 173 | Write(MD.get()); | ||||
| 174 | } | ||||
| 175 | |||||
| 176 | void Write(const NamedMDNode *NMD) { | ||||
| 177 | if (!NMD) | ||||
| 178 | return; | ||||
| 179 | NMD->print(*OS, MST); | ||||
| 180 | *OS << '\n'; | ||||
| 181 | } | ||||
| 182 | |||||
| 183 | void Write(Type *T) { | ||||
| 184 | if (!T) | ||||
| 185 | return; | ||||
| 186 | *OS << ' ' << *T; | ||||
| 187 | } | ||||
| 188 | |||||
| 189 | void Write(const Comdat *C) { | ||||
| 190 | if (!C) | ||||
| 191 | return; | ||||
| 192 | *OS << *C; | ||||
| 193 | } | ||||
| 194 | |||||
| 195 | void Write(const APInt *AI) { | ||||
| 196 | if (!AI) | ||||
| 197 | return; | ||||
| 198 | *OS << *AI << '\n'; | ||||
| 199 | } | ||||
| 200 | |||||
| 201 | void Write(const unsigned i) { *OS << i << '\n'; } | ||||
| 202 | |||||
| 203 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 204 | void Write(const Attribute *A) { | ||||
| 205 | if (!A) | ||||
| 206 | return; | ||||
| 207 | *OS << A->getAsString() << '\n'; | ||||
| 208 | } | ||||
| 209 | |||||
| 210 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 211 | void Write(const AttributeSet *AS) { | ||||
| 212 | if (!AS) | ||||
| 213 | return; | ||||
| 214 | *OS << AS->getAsString() << '\n'; | ||||
| 215 | } | ||||
| 216 | |||||
| 217 | // NOLINTNEXTLINE(readability-identifier-naming) | ||||
| 218 | void Write(const AttributeList *AL) { | ||||
| 219 | if (!AL) | ||||
| 220 | return; | ||||
| 221 | AL->print(*OS); | ||||
| 222 | } | ||||
| 223 | |||||
| 224 | template <typename T> void Write(ArrayRef<T> Vs) { | ||||
| 225 | for (const T &V : Vs) | ||||
| 226 | Write(V); | ||||
| 227 | } | ||||
| 228 | |||||
| 229 | template <typename T1, typename... Ts> | ||||
| 230 | void WriteTs(const T1 &V1, const Ts &... Vs) { | ||||
| 231 | Write(V1); | ||||
| 232 | WriteTs(Vs...); | ||||
| 233 | } | ||||
| 234 | |||||
| 235 | template <typename... Ts> void WriteTs() {} | ||||
| 236 | |||||
| 237 | public: | ||||
| 238 | /// A check failed, so printout out the condition and the message. | ||||
| 239 | /// | ||||
| 240 | /// This provides a nice place to put a breakpoint if you want to see why | ||||
| 241 | /// something is not correct. | ||||
| 242 | void CheckFailed(const Twine &Message) { | ||||
| 243 | if (OS) | ||||
| 244 | *OS << Message << '\n'; | ||||
| 245 | Broken = true; | ||||
| 246 | } | ||||
| 247 | |||||
| 248 | /// A check failed (with values to print). | ||||
| 249 | /// | ||||
| 250 | /// This calls the Message-only version so that the above is easier to set a | ||||
| 251 | /// breakpoint on. | ||||
| 252 | template <typename T1, typename... Ts> | ||||
| 253 | void CheckFailed(const Twine &Message, const T1 &V1, const Ts &... Vs) { | ||||
| 254 | CheckFailed(Message); | ||||
| 255 | if (OS) | ||||
| 256 | WriteTs(V1, Vs...); | ||||
| 257 | } | ||||
| 258 | |||||
| 259 | /// A debug info check failed. | ||||
| 260 | void DebugInfoCheckFailed(const Twine &Message) { | ||||
| 261 | if (OS) | ||||
| 262 | *OS << Message << '\n'; | ||||
| 263 | Broken |= TreatBrokenDebugInfoAsError; | ||||
| 264 | BrokenDebugInfo = true; | ||||
| 265 | } | ||||
| 266 | |||||
| 267 | /// A debug info check failed (with values to print). | ||||
| 268 | template <typename T1, typename... Ts> | ||||
| 269 | void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, | ||||
| 270 | const Ts &... Vs) { | ||||
| 271 | DebugInfoCheckFailed(Message); | ||||
| 272 | if (OS) | ||||
| 273 | WriteTs(V1, Vs...); | ||||
| 274 | } | ||||
| 275 | }; | ||||
| 276 | |||||
| 277 | } // namespace llvm | ||||
| 278 | |||||
| 279 | namespace { | ||||
| 280 | |||||
| 281 | class Verifier : public InstVisitor<Verifier>, VerifierSupport { | ||||
| 282 | friend class InstVisitor<Verifier>; | ||||
| 283 | |||||
| 284 | // ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so | ||||
| 285 | // the alignment size should not exceed 2^15. Since encode(Align) | ||||
| 286 | // would plus the shift value by 1, the alignment size should | ||||
| 287 | // not exceed 2^14, otherwise it can NOT be properly lowered | ||||
| 288 | // in backend. | ||||
| 289 | static constexpr unsigned ParamMaxAlignment = 1 << 14; | ||||
| 290 | DominatorTree DT; | ||||
| 291 | |||||
| 292 | /// When verifying a basic block, keep track of all of the | ||||
| 293 | /// instructions we have seen so far. | ||||
| 294 | /// | ||||
| 295 | /// This allows us to do efficient dominance checks for the case when an | ||||
| 296 | /// instruction has an operand that is an instruction in the same block. | ||||
| 297 | SmallPtrSet<Instruction *, 16> InstsInThisBlock; | ||||
| 298 | |||||
| 299 | /// Keep track of the metadata nodes that have been checked already. | ||||
| 300 | SmallPtrSet<const Metadata *, 32> MDNodes; | ||||
| 301 | |||||
| 302 | /// Keep track which DISubprogram is attached to which function. | ||||
| 303 | DenseMap<const DISubprogram *, const Function *> DISubprogramAttachments; | ||||
| 304 | |||||
| 305 | /// Track all DICompileUnits visited. | ||||
| 306 | SmallPtrSet<const Metadata *, 2> CUVisited; | ||||
| 307 | |||||
| 308 | /// The result type for a landingpad. | ||||
| 309 | Type *LandingPadResultTy; | ||||
| 310 | |||||
| 311 | /// Whether we've seen a call to @llvm.localescape in this function | ||||
| 312 | /// already. | ||||
| 313 | bool SawFrameEscape; | ||||
| 314 | |||||
| 315 | /// Whether the current function has a DISubprogram attached to it. | ||||
| 316 | bool HasDebugInfo = false; | ||||
| 317 | |||||
| 318 | /// The current source language. | ||||
| 319 | dwarf::SourceLanguage CurrentSourceLang = dwarf::DW_LANG_lo_user; | ||||
| 320 | |||||
| 321 | /// Whether source was present on the first DIFile encountered in each CU. | ||||
| 322 | DenseMap<const DICompileUnit *, bool> HasSourceDebugInfo; | ||||
| 323 | |||||
| 324 | /// Stores the count of how many objects were passed to llvm.localescape for a | ||||
| 325 | /// given function and the largest index passed to llvm.localrecover. | ||||
| 326 | DenseMap<Function *, std::pair<unsigned, unsigned>> FrameEscapeInfo; | ||||
| 327 | |||||
| 328 | // Maps catchswitches and cleanuppads that unwind to siblings to the | ||||
| 329 | // terminators that indicate the unwind, used to detect cycles therein. | ||||
| 330 | MapVector<Instruction *, Instruction *> SiblingFuncletInfo; | ||||
| 331 | |||||
| 332 | /// Cache which blocks are in which funclet, if an EH funclet personality is | ||||
| 333 | /// in use. Otherwise empty. | ||||
| 334 | DenseMap<BasicBlock *, ColorVector> BlockEHFuncletColors; | ||||
| 335 | |||||
| 336 | /// Cache of constants visited in search of ConstantExprs. | ||||
| 337 | SmallPtrSet<const Constant *, 32> ConstantExprVisited; | ||||
| 338 | |||||
| 339 | /// Cache of declarations of the llvm.experimental.deoptimize.<ty> intrinsic. | ||||
| 340 | SmallVector<const Function *, 4> DeoptimizeDeclarations; | ||||
| 341 | |||||
| 342 | /// Cache of attribute lists verified. | ||||
| 343 | SmallPtrSet<const void *, 32> AttributeListsVisited; | ||||
| 344 | |||||
| 345 | // Verify that this GlobalValue is only used in this module. | ||||
| 346 | // This map is used to avoid visiting uses twice. We can arrive at a user | ||||
| 347 | // twice, if they have multiple operands. In particular for very large | ||||
| 348 | // constant expressions, we can arrive at a particular user many times. | ||||
| 349 | SmallPtrSet<const Value *, 32> GlobalValueVisited; | ||||
| 350 | |||||
| 351 | // Keeps track of duplicate function argument debug info. | ||||
| 352 | SmallVector<const DILocalVariable *, 16> DebugFnArgs; | ||||
| 353 | |||||
| 354 | TBAAVerifier TBAAVerifyHelper; | ||||
| 355 | |||||
| 356 | SmallVector<IntrinsicInst *, 4> NoAliasScopeDecls; | ||||
| 357 | |||||
| 358 | void checkAtomicMemAccessSize(Type *Ty, const Instruction *I); | ||||
| 359 | |||||
| 360 | public: | ||||
| 361 | explicit Verifier(raw_ostream *OS, bool ShouldTreatBrokenDebugInfoAsError, | ||||
| 362 | const Module &M) | ||||
| 363 | : VerifierSupport(OS, M), LandingPadResultTy(nullptr), | ||||
| 364 | SawFrameEscape(false), TBAAVerifyHelper(this) { | ||||
| 365 | TreatBrokenDebugInfoAsError = ShouldTreatBrokenDebugInfoAsError; | ||||
| 366 | } | ||||
| 367 | |||||
| 368 | bool hasBrokenDebugInfo() const { return BrokenDebugInfo; } | ||||
| 369 | |||||
| 370 | bool verify(const Function &F) { | ||||
| 371 | assert(F.getParent() == &M &&(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "llvm/lib/IR/Verifier.cpp", 372, __extension__ __PRETTY_FUNCTION__ )) | ||||
| 372 | "An instance of this class only works with a specific module!")(static_cast <bool> (F.getParent() == &M && "An instance of this class only works with a specific module!" ) ? void (0) : __assert_fail ("F.getParent() == &M && \"An instance of this class only works with a specific module!\"" , "llvm/lib/IR/Verifier.cpp", 372, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 373 | |||||
| 374 | // First ensure the function is well-enough formed to compute dominance | ||||
| 375 | // information, and directly compute a dominance tree. We don't rely on the | ||||
| 376 | // pass manager to provide this as it isolates us from a potentially | ||||
| 377 | // out-of-date dominator tree and makes it significantly more complex to run | ||||
| 378 | // this code outside of a pass manager. | ||||
| 379 | // FIXME: It's really gross that we have to cast away constness here. | ||||
| 380 | if (!F.empty()) | ||||
| 381 | DT.recalculate(const_cast<Function &>(F)); | ||||
| 382 | |||||
| 383 | for (const BasicBlock &BB : F) { | ||||
| 384 | if (!BB.empty() && BB.back().isTerminator()) | ||||
| 385 | continue; | ||||
| 386 | |||||
| 387 | if (OS) { | ||||
| 388 | *OS << "Basic Block in function '" << F.getName() | ||||
| 389 | << "' does not have terminator!\n"; | ||||
| 390 | BB.printAsOperand(*OS, true, MST); | ||||
| 391 | *OS << "\n"; | ||||
| 392 | } | ||||
| 393 | return false; | ||||
| 394 | } | ||||
| 395 | |||||
| 396 | Broken = false; | ||||
| 397 | // FIXME: We strip const here because the inst visitor strips const. | ||||
| 398 | visit(const_cast<Function &>(F)); | ||||
| 399 | verifySiblingFuncletUnwinds(); | ||||
| 400 | InstsInThisBlock.clear(); | ||||
| 401 | DebugFnArgs.clear(); | ||||
| 402 | LandingPadResultTy = nullptr; | ||||
| 403 | SawFrameEscape = false; | ||||
| 404 | SiblingFuncletInfo.clear(); | ||||
| 405 | verifyNoAliasScopeDecl(); | ||||
| 406 | NoAliasScopeDecls.clear(); | ||||
| 407 | |||||
| 408 | return !Broken; | ||||
| 409 | } | ||||
| 410 | |||||
| 411 | /// Verify the module that this instance of \c Verifier was initialized with. | ||||
| 412 | bool verify() { | ||||
| 413 | Broken = false; | ||||
| 414 | |||||
| 415 | // Collect all declarations of the llvm.experimental.deoptimize intrinsic. | ||||
| 416 | for (const Function &F : M) | ||||
| 417 | if (F.getIntrinsicID() == Intrinsic::experimental_deoptimize) | ||||
| 418 | DeoptimizeDeclarations.push_back(&F); | ||||
| 419 | |||||
| 420 | // Now that we've visited every function, verify that we never asked to | ||||
| 421 | // recover a frame index that wasn't escaped. | ||||
| 422 | verifyFrameRecoverIndices(); | ||||
| 423 | for (const GlobalVariable &GV : M.globals()) | ||||
| 424 | visitGlobalVariable(GV); | ||||
| 425 | |||||
| 426 | for (const GlobalAlias &GA : M.aliases()) | ||||
| 427 | visitGlobalAlias(GA); | ||||
| 428 | |||||
| 429 | for (const GlobalIFunc &GI : M.ifuncs()) | ||||
| 430 | visitGlobalIFunc(GI); | ||||
| 431 | |||||
| 432 | for (const NamedMDNode &NMD : M.named_metadata()) | ||||
| 433 | visitNamedMDNode(NMD); | ||||
| 434 | |||||
| 435 | for (const StringMapEntry<Comdat> &SMEC : M.getComdatSymbolTable()) | ||||
| 436 | visitComdat(SMEC.getValue()); | ||||
| 437 | |||||
| 438 | visitModuleFlags(); | ||||
| 439 | visitModuleIdents(); | ||||
| 440 | visitModuleCommandLines(); | ||||
| 441 | |||||
| 442 | verifyCompileUnits(); | ||||
| 443 | |||||
| 444 | verifyDeoptimizeCallingConvs(); | ||||
| 445 | DISubprogramAttachments.clear(); | ||||
| 446 | return !Broken; | ||||
| 447 | } | ||||
| 448 | |||||
| 449 | private: | ||||
| 450 | /// Whether a metadata node is allowed to be, or contain, a DILocation. | ||||
| 451 | enum class AreDebugLocsAllowed { No, Yes }; | ||||
| 452 | |||||
| 453 | // Verification methods... | ||||
| 454 | void visitGlobalValue(const GlobalValue &GV); | ||||
| 455 | void visitGlobalVariable(const GlobalVariable &GV); | ||||
| 456 | void visitGlobalAlias(const GlobalAlias &GA); | ||||
| 457 | void visitGlobalIFunc(const GlobalIFunc &GI); | ||||
| 458 | void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); | ||||
| 459 | void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited, | ||||
| 460 | const GlobalAlias &A, const Constant &C); | ||||
| 461 | void visitNamedMDNode(const NamedMDNode &NMD); | ||||
| 462 | void visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs); | ||||
| 463 | void visitMetadataAsValue(const MetadataAsValue &MD, Function *F); | ||||
| 464 | void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); | ||||
| 465 | void visitComdat(const Comdat &C); | ||||
| 466 | void visitModuleIdents(); | ||||
| 467 | void visitModuleCommandLines(); | ||||
| 468 | void visitModuleFlags(); | ||||
| 469 | void visitModuleFlag(const MDNode *Op, | ||||
| 470 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
| 471 | SmallVectorImpl<const MDNode *> &Requirements); | ||||
| 472 | void visitModuleFlagCGProfileEntry(const MDOperand &MDO); | ||||
| 473 | void visitFunction(const Function &F); | ||||
| 474 | void visitBasicBlock(BasicBlock &BB); | ||||
| 475 | void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); | ||||
| 476 | void visitDereferenceableMetadata(Instruction &I, MDNode *MD); | ||||
| 477 | void visitProfMetadata(Instruction &I, MDNode *MD); | ||||
| 478 | void visitCallStackMetadata(MDNode *MD); | ||||
| 479 | void visitMemProfMetadata(Instruction &I, MDNode *MD); | ||||
| 480 | void visitCallsiteMetadata(Instruction &I, MDNode *MD); | ||||
| 481 | void visitDIAssignIDMetadata(Instruction &I, MDNode *MD); | ||||
| 482 | void visitAnnotationMetadata(MDNode *Annotation); | ||||
| 483 | void visitAliasScopeMetadata(const MDNode *MD); | ||||
| 484 | void visitAliasScopeListMetadata(const MDNode *MD); | ||||
| 485 | void visitAccessGroupMetadata(const MDNode *MD); | ||||
| 486 | |||||
| 487 | template <class Ty> bool isValidMetadataArray(const MDTuple &N); | ||||
| 488 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); | ||||
| 489 | #include "llvm/IR/Metadata.def" | ||||
| 490 | void visitDIScope(const DIScope &N); | ||||
| 491 | void visitDIVariable(const DIVariable &N); | ||||
| 492 | void visitDILexicalBlockBase(const DILexicalBlockBase &N); | ||||
| 493 | void visitDITemplateParameter(const DITemplateParameter &N); | ||||
| 494 | |||||
| 495 | void visitTemplateParams(const MDNode &N, const Metadata &RawParams); | ||||
| 496 | |||||
| 497 | // InstVisitor overrides... | ||||
| 498 | using InstVisitor<Verifier>::visit; | ||||
| 499 | void visit(Instruction &I); | ||||
| 500 | |||||
| 501 | void visitTruncInst(TruncInst &I); | ||||
| 502 | void visitZExtInst(ZExtInst &I); | ||||
| 503 | void visitSExtInst(SExtInst &I); | ||||
| 504 | void visitFPTruncInst(FPTruncInst &I); | ||||
| 505 | void visitFPExtInst(FPExtInst &I); | ||||
| 506 | void visitFPToUIInst(FPToUIInst &I); | ||||
| 507 | void visitFPToSIInst(FPToSIInst &I); | ||||
| 508 | void visitUIToFPInst(UIToFPInst &I); | ||||
| 509 | void visitSIToFPInst(SIToFPInst &I); | ||||
| 510 | void visitIntToPtrInst(IntToPtrInst &I); | ||||
| 511 | void visitPtrToIntInst(PtrToIntInst &I); | ||||
| 512 | void visitBitCastInst(BitCastInst &I); | ||||
| 513 | void visitAddrSpaceCastInst(AddrSpaceCastInst &I); | ||||
| 514 | void visitPHINode(PHINode &PN); | ||||
| 515 | void visitCallBase(CallBase &Call); | ||||
| 516 | void visitUnaryOperator(UnaryOperator &U); | ||||
| 517 | void visitBinaryOperator(BinaryOperator &B); | ||||
| 518 | void visitICmpInst(ICmpInst &IC); | ||||
| 519 | void visitFCmpInst(FCmpInst &FC); | ||||
| 520 | void visitExtractElementInst(ExtractElementInst &EI); | ||||
| 521 | void visitInsertElementInst(InsertElementInst &EI); | ||||
| 522 | void visitShuffleVectorInst(ShuffleVectorInst &EI); | ||||
| 523 | void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } | ||||
| 524 | void visitCallInst(CallInst &CI); | ||||
| 525 | void visitInvokeInst(InvokeInst &II); | ||||
| 526 | void visitGetElementPtrInst(GetElementPtrInst &GEP); | ||||
| 527 | void visitLoadInst(LoadInst &LI); | ||||
| 528 | void visitStoreInst(StoreInst &SI); | ||||
| 529 | void verifyDominatesUse(Instruction &I, unsigned i); | ||||
| 530 | void visitInstruction(Instruction &I); | ||||
| 531 | void visitTerminator(Instruction &I); | ||||
| 532 | void visitBranchInst(BranchInst &BI); | ||||
| 533 | void visitReturnInst(ReturnInst &RI); | ||||
| 534 | void visitSwitchInst(SwitchInst &SI); | ||||
| 535 | void visitIndirectBrInst(IndirectBrInst &BI); | ||||
| 536 | void visitCallBrInst(CallBrInst &CBI); | ||||
| 537 | void visitSelectInst(SelectInst &SI); | ||||
| 538 | void visitUserOp1(Instruction &I); | ||||
| 539 | void visitUserOp2(Instruction &I) { visitUserOp1(I); } | ||||
| 540 | void visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call); | ||||
| 541 | void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); | ||||
| 542 | void visitVPIntrinsic(VPIntrinsic &VPI); | ||||
| 543 | void visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII); | ||||
| 544 | void visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI); | ||||
| 545 | void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI); | ||||
| 546 | void visitAtomicRMWInst(AtomicRMWInst &RMWI); | ||||
| 547 | void visitFenceInst(FenceInst &FI); | ||||
| 548 | void visitAllocaInst(AllocaInst &AI); | ||||
| 549 | void visitExtractValueInst(ExtractValueInst &EVI); | ||||
| 550 | void visitInsertValueInst(InsertValueInst &IVI); | ||||
| 551 | void visitEHPadPredecessors(Instruction &I); | ||||
| 552 | void visitLandingPadInst(LandingPadInst &LPI); | ||||
| 553 | void visitResumeInst(ResumeInst &RI); | ||||
| 554 | void visitCatchPadInst(CatchPadInst &CPI); | ||||
| 555 | void visitCatchReturnInst(CatchReturnInst &CatchReturn); | ||||
| 556 | void visitCleanupPadInst(CleanupPadInst &CPI); | ||||
| 557 | void visitFuncletPadInst(FuncletPadInst &FPI); | ||||
| 558 | void visitCatchSwitchInst(CatchSwitchInst &CatchSwitch); | ||||
| 559 | void visitCleanupReturnInst(CleanupReturnInst &CRI); | ||||
| 560 | |||||
| 561 | void verifySwiftErrorCall(CallBase &Call, const Value *SwiftErrorVal); | ||||
| 562 | void verifySwiftErrorValue(const Value *SwiftErrorVal); | ||||
| 563 | void verifyTailCCMustTailAttrs(const AttrBuilder &Attrs, StringRef Context); | ||||
| 564 | void verifyMustTailCall(CallInst &CI); | ||||
| 565 | bool verifyAttributeCount(AttributeList Attrs, unsigned Params); | ||||
| 566 | void verifyAttributeTypes(AttributeSet Attrs, const Value *V); | ||||
| 567 | void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V); | ||||
| 568 | void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
| 569 | const Value *V); | ||||
| 570 | void verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
| 571 | const Value *V, bool IsIntrinsic, bool IsInlineAsm); | ||||
| 572 | void verifyFunctionMetadata(ArrayRef<std::pair<unsigned, MDNode *>> MDs); | ||||
| 573 | |||||
| 574 | void visitConstantExprsRecursively(const Constant *EntryC); | ||||
| 575 | void visitConstantExpr(const ConstantExpr *CE); | ||||
| 576 | void verifyInlineAsmCall(const CallBase &Call); | ||||
| 577 | void verifyStatepoint(const CallBase &Call); | ||||
| 578 | void verifyFrameRecoverIndices(); | ||||
| 579 | void verifySiblingFuncletUnwinds(); | ||||
| 580 | |||||
| 581 | void verifyFragmentExpression(const DbgVariableIntrinsic &I); | ||||
| 582 | template <typename ValueOrMetadata> | ||||
| 583 | void verifyFragmentExpression(const DIVariable &V, | ||||
| 584 | DIExpression::FragmentInfo Fragment, | ||||
| 585 | ValueOrMetadata *Desc); | ||||
| 586 | void verifyFnArgs(const DbgVariableIntrinsic &I); | ||||
| 587 | void verifyNotEntryValue(const DbgVariableIntrinsic &I); | ||||
| 588 | |||||
| 589 | /// Module-level debug info verification... | ||||
| 590 | void verifyCompileUnits(); | ||||
| 591 | |||||
| 592 | /// Module-level verification that all @llvm.experimental.deoptimize | ||||
| 593 | /// declarations share the same calling convention. | ||||
| 594 | void verifyDeoptimizeCallingConvs(); | ||||
| 595 | |||||
| 596 | void verifyAttachedCallBundle(const CallBase &Call, | ||||
| 597 | const OperandBundleUse &BU); | ||||
| 598 | |||||
| 599 | /// Verify all-or-nothing property of DIFile source attribute within a CU. | ||||
| 600 | void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F); | ||||
| 601 | |||||
| 602 | /// Verify the llvm.experimental.noalias.scope.decl declarations | ||||
| 603 | void verifyNoAliasScopeDecl(); | ||||
| 604 | }; | ||||
| 605 | |||||
| 606 | } // end anonymous namespace | ||||
| 607 | |||||
| 608 | /// We know that cond should be true, if not print an error message. | ||||
| 609 | #define Check(C, ...)do { if (!(C)) { CheckFailed(...); return; } } while (false) \ | ||||
| 610 | do { \ | ||||
| 611 | if (!(C)) { \ | ||||
| 612 | CheckFailed(__VA_ARGS__); \ | ||||
| 613 | return; \ | ||||
| 614 | } \ | ||||
| 615 | } while (false) | ||||
| 616 | |||||
| 617 | /// We know that a debug info condition should be true, if not print | ||||
| 618 | /// an error message. | ||||
| 619 | #define CheckDI(C, ...)do { if (!(C)) { DebugInfoCheckFailed(...); return; } } while (false) \ | ||||
| 620 | do { \ | ||||
| 621 | if (!(C)) { \ | ||||
| 622 | DebugInfoCheckFailed(__VA_ARGS__); \ | ||||
| 623 | return; \ | ||||
| 624 | } \ | ||||
| 625 | } while (false) | ||||
| 626 | |||||
| 627 | void Verifier::visit(Instruction &I) { | ||||
| 628 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) | ||||
| 629 | Check(I.getOperand(i) != nullptr, "Operand is null", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Operand is null" , &I); return; } } while (false); | ||||
| 630 | InstVisitor<Verifier>::visit(I); | ||||
| 631 | } | ||||
| 632 | |||||
| 633 | // Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further. | ||||
| 634 | static void forEachUser(const Value *User, | ||||
| 635 | SmallPtrSet<const Value *, 32> &Visited, | ||||
| 636 | llvm::function_ref<bool(const Value *)> Callback) { | ||||
| 637 | if (!Visited.insert(User).second) | ||||
| 638 | return; | ||||
| 639 | |||||
| 640 | SmallVector<const Value *> WorkList; | ||||
| 641 | append_range(WorkList, User->materialized_users()); | ||||
| 642 | while (!WorkList.empty()) { | ||||
| 643 | const Value *Cur = WorkList.pop_back_val(); | ||||
| 644 | if (!Visited.insert(Cur).second) | ||||
| 645 | continue; | ||||
| 646 | if (Callback(Cur)) | ||||
| 647 | append_range(WorkList, Cur->materialized_users()); | ||||
| 648 | } | ||||
| 649 | } | ||||
| 650 | |||||
| 651 | void Verifier::visitGlobalValue(const GlobalValue &GV) { | ||||
| 652 | Check(!GV.isDeclaration() || GV.hasValidDeclarationLinkage(),do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false) | ||||
| 653 | "Global is external, but doesn't have external or weak linkage!", &GV)do { if (!(!GV.isDeclaration() || GV.hasValidDeclarationLinkage ())) { CheckFailed("Global is external, but doesn't have external or weak linkage!" , &GV); return; } } while (false); | ||||
| 654 | |||||
| 655 | if (const GlobalObject *GO = dyn_cast<GlobalObject>(&GV)) { | ||||
| 656 | |||||
| 657 | if (MaybeAlign A = GO->getAlign()) { | ||||
| 658 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", GO); return; } } while (false) | ||||
| 659 | "huge alignment values are unsupported", GO)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", GO); return; } } while (false); | ||||
| 660 | } | ||||
| 661 | |||||
| 662 | if (const MDNode *Associated = | ||||
| 663 | GO->getMetadata(LLVMContext::MD_associated)) { | ||||
| 664 | Check(Associated->getNumOperands() == 1,do { if (!(Associated->getNumOperands() == 1)) { CheckFailed ("associated metadata must have one operand", &GV, Associated ); return; } } while (false) | ||||
| 665 | "associated metadata must have one operand", &GV, Associated)do { if (!(Associated->getNumOperands() == 1)) { CheckFailed ("associated metadata must have one operand", &GV, Associated ); return; } } while (false); | ||||
| 666 | const Metadata *Op = Associated->getOperand(0).get(); | ||||
| 667 | Check(Op, "associated metadata must have a global value", GO, Associated)do { if (!(Op)) { CheckFailed("associated metadata must have a global value" , GO, Associated); return; } } while (false); | ||||
| 668 | |||||
| 669 | const auto *VM = dyn_cast_or_null<ValueAsMetadata>(Op); | ||||
| 670 | Check(VM, "associated metadata must be ValueAsMetadata", GO, Associated)do { if (!(VM)) { CheckFailed("associated metadata must be ValueAsMetadata" , GO, Associated); return; } } while (false); | ||||
| 671 | if (VM) { | ||||
| 672 | Check(isa<PointerType>(VM->getValue()->getType()),do { if (!(isa<PointerType>(VM->getValue()->getType ()))) { CheckFailed("associated value must be pointer typed", GV, Associated); return; } } while (false) | ||||
| 673 | "associated value must be pointer typed", GV, Associated)do { if (!(isa<PointerType>(VM->getValue()->getType ()))) { CheckFailed("associated value must be pointer typed", GV, Associated); return; } } while (false); | ||||
| 674 | |||||
| 675 | const Value *Stripped = VM->getValue()->stripPointerCastsAndAliases(); | ||||
| 676 | Check(isa<GlobalObject>(Stripped) || isa<Constant>(Stripped),do { if (!(isa<GlobalObject>(Stripped) || isa<Constant >(Stripped))) { CheckFailed("associated metadata must point to a GlobalObject" , GO, Stripped); return; } } while (false) | ||||
| 677 | "associated metadata must point to a GlobalObject", GO, Stripped)do { if (!(isa<GlobalObject>(Stripped) || isa<Constant >(Stripped))) { CheckFailed("associated metadata must point to a GlobalObject" , GO, Stripped); return; } } while (false); | ||||
| 678 | Check(Stripped != GO,do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false) | ||||
| 679 | "global values should not associate to themselves", GO,do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false) | ||||
| 680 | Associated)do { if (!(Stripped != GO)) { CheckFailed("global values should not associate to themselves" , GO, Associated); return; } } while (false); | ||||
| 681 | } | ||||
| 682 | } | ||||
| 683 | } | ||||
| 684 | Check(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false) | ||||
| 685 | "Only global variables can have appending linkage!", &GV)do { if (!(!GV.hasAppendingLinkage() || isa<GlobalVariable >(GV))) { CheckFailed("Only global variables can have appending linkage!" , &GV); return; } } while (false); | ||||
| 686 | |||||
| 687 | if (GV.hasAppendingLinkage()) { | ||||
| 688 | const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV); | ||||
| 689 | Check(GVar && GVar->getValueType()->isArrayTy(),do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false) | ||||
| 690 | "Only global arrays can have appending linkage!", GVar)do { if (!(GVar && GVar->getValueType()->isArrayTy ())) { CheckFailed("Only global arrays can have appending linkage!" , GVar); return; } } while (false); | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | if (GV.isDeclarationForLinker()) | ||||
| 694 | Check(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("Declaration may not be in a Comdat!" , &GV); return; } } while (false); | ||||
| 695 | |||||
| 696 | if (GV.hasDLLExportStorageClass()) { | ||||
| 697 | Check(!GV.hasHiddenVisibility(),do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false) | ||||
| 698 | "dllexport GlobalValue must have default or protected visibility",do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false) | ||||
| 699 | &GV)do { if (!(!GV.hasHiddenVisibility())) { CheckFailed("dllexport GlobalValue must have default or protected visibility" , &GV); return; } } while (false); | ||||
| 700 | } | ||||
| 701 | if (GV.hasDLLImportStorageClass()) { | ||||
| 702 | Check(GV.hasDefaultVisibility(),do { if (!(GV.hasDefaultVisibility())) { CheckFailed("dllimport GlobalValue must have default visibility" , &GV); return; } } while (false) | ||||
| 703 | "dllimport GlobalValue must have default visibility", &GV)do { if (!(GV.hasDefaultVisibility())) { CheckFailed("dllimport GlobalValue must have default visibility" , &GV); return; } } while (false); | ||||
| 704 | Check(!GV.isDSOLocal(), "GlobalValue with DLLImport Storage is dso_local!",do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false) | ||||
| 705 | &GV)do { if (!(!GV.isDSOLocal())) { CheckFailed("GlobalValue with DLLImport Storage is dso_local!" , &GV); return; } } while (false); | ||||
| 706 | |||||
| 707 | Check((GV.isDeclaration() &&do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 708 | (GV.hasExternalLinkage() || GV.hasExternalWeakLinkage())) ||do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 709 | GV.hasAvailableExternallyLinkage(),do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false) | ||||
| 710 | "Global is marked as dllimport, but not external", &GV)do { if (!((GV.isDeclaration() && (GV.hasExternalLinkage () || GV.hasExternalWeakLinkage())) || GV.hasAvailableExternallyLinkage ())) { CheckFailed("Global is marked as dllimport, but not external" , &GV); return; } } while (false); | ||||
| 711 | } | ||||
| 712 | |||||
| 713 | if (GV.isImplicitDSOLocal()) | ||||
| 714 | Check(GV.isDSOLocal(),do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 715 | "GlobalValue with local linkage or non-default "do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 716 | "visibility must be dso_local!",do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false) | ||||
| 717 | &GV)do { if (!(GV.isDSOLocal())) { CheckFailed("GlobalValue with local linkage or non-default " "visibility must be dso_local!", &GV); return; } } while (false); | ||||
| 718 | |||||
| 719 | forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool { | ||||
| 720 | if (const Instruction *I = dyn_cast<Instruction>(V)) { | ||||
| 721 | if (!I->getParent() || !I->getParent()->getParent()) | ||||
| 722 | CheckFailed("Global is referenced by parentless instruction!", &GV, &M, | ||||
| 723 | I); | ||||
| 724 | else if (I->getParent()->getParent()->getParent() != &M) | ||||
| 725 | CheckFailed("Global is referenced in a different module!", &GV, &M, I, | ||||
| 726 | I->getParent()->getParent(), | ||||
| 727 | I->getParent()->getParent()->getParent()); | ||||
| 728 | return false; | ||||
| 729 | } else if (const Function *F = dyn_cast<Function>(V)) { | ||||
| 730 | if (F->getParent() != &M) | ||||
| 731 | CheckFailed("Global is used by function in a different module", &GV, &M, | ||||
| 732 | F, F->getParent()); | ||||
| 733 | return false; | ||||
| 734 | } | ||||
| 735 | return true; | ||||
| 736 | }); | ||||
| 737 | } | ||||
| 738 | |||||
| 739 | void Verifier::visitGlobalVariable(const GlobalVariable &GV) { | ||||
| 740 | if (GV.hasInitializer()) { | ||||
| 741 | Check(GV.getInitializer()->getType() == GV.getValueType(),do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 742 | "Global variable initializer type does not match global "do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 743 | "variable type!",do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false) | ||||
| 744 | &GV)do { if (!(GV.getInitializer()->getType() == GV.getValueType ())) { CheckFailed("Global variable initializer type does not match global " "variable type!", &GV); return; } } while (false); | ||||
| 745 | // If the global has common linkage, it must have a zero initializer and | ||||
| 746 | // cannot be constant. | ||||
| 747 | if (GV.hasCommonLinkage()) { | ||||
| 748 | Check(GV.getInitializer()->isNullValue(),do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false) | ||||
| 749 | "'common' global must have a zero initializer!", &GV)do { if (!(GV.getInitializer()->isNullValue())) { CheckFailed ("'common' global must have a zero initializer!", &GV); return ; } } while (false); | ||||
| 750 | Check(!GV.isConstant(), "'common' global may not be marked constant!",do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false) | ||||
| 751 | &GV)do { if (!(!GV.isConstant())) { CheckFailed("'common' global may not be marked constant!" , &GV); return; } } while (false); | ||||
| 752 | Check(!GV.hasComdat(), "'common' global may not be in a Comdat!", &GV)do { if (!(!GV.hasComdat())) { CheckFailed("'common' global may not be in a Comdat!" , &GV); return; } } while (false); | ||||
| 753 | } | ||||
| 754 | } | ||||
| 755 | |||||
| 756 | if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || | ||||
| 757 | GV.getName() == "llvm.global_dtors")) { | ||||
| 758 | Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 759 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 760 | Check(GV.materialized_use_empty(),do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false) | ||||
| 761 | "invalid uses of intrinsic global variable", &GV)do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false); | ||||
| 762 | |||||
| 763 | // Don't worry about emitting an error for it not being an array, | ||||
| 764 | // visitGlobalValue will complain on appending non-array. | ||||
| 765 | if (ArrayType *ATy = dyn_cast<ArrayType>(GV.getValueType())) { | ||||
| 766 | StructType *STy = dyn_cast<StructType>(ATy->getElementType()); | ||||
| 767 | PointerType *FuncPtrTy = | ||||
| 768 | FunctionType::get(Type::getVoidTy(Context), false)-> | ||||
| 769 | getPointerTo(DL.getProgramAddressSpace()); | ||||
| 770 | Check(STy && (STy->getNumElements() == 2 || STy->getNumElements() == 3) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 771 | STy->getTypeAtIndex(0u)->isIntegerTy(32) &&do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 772 | STy->getTypeAtIndex(1) == FuncPtrTy,do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 773 | "wrong type for intrinsic global variable", &GV)do { if (!(STy && (STy->getNumElements() == 2 || STy ->getNumElements() == 3) && STy->getTypeAtIndex (0u)->isIntegerTy(32) && STy->getTypeAtIndex(1) == FuncPtrTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 774 | Check(STy->getNumElements() == 3,do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
| 775 | "the third field of the element type is mandatory, "do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false) | ||||
| 776 | "specify ptr null to migrate from the obsoleted 2-field form")do { if (!(STy->getNumElements() == 3)) { CheckFailed("the third field of the element type is mandatory, " "specify ptr null to migrate from the obsoleted 2-field form" ); return; } } while (false); | ||||
| 777 | Type *ETy = STy->getTypeAtIndex(2); | ||||
| 778 | Type *Int8Ty = Type::getInt8Ty(ETy->getContext()); | ||||
| 779 | Check(ETy->isPointerTy() &&do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
| 780 | cast<PointerType>(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty),do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false) | ||||
| 781 | "wrong type for intrinsic global variable", &GV)do { if (!(ETy->isPointerTy() && cast<PointerType >(ETy)->isOpaqueOrPointeeTypeMatches(Int8Ty))) { CheckFailed ("wrong type for intrinsic global variable", &GV); return ; } } while (false); | ||||
| 782 | } | ||||
| 783 | } | ||||
| 784 | |||||
| 785 | if (GV.hasName() && (GV.getName() == "llvm.used" || | ||||
| 786 | GV.getName() == "llvm.compiler.used")) { | ||||
| 787 | Check(!GV.hasInitializer() || GV.hasAppendingLinkage(),do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false) | ||||
| 788 | "invalid linkage for intrinsic global variable", &GV)do { if (!(!GV.hasInitializer() || GV.hasAppendingLinkage())) { CheckFailed("invalid linkage for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 789 | Check(GV.materialized_use_empty(),do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false) | ||||
| 790 | "invalid uses of intrinsic global variable", &GV)do { if (!(GV.materialized_use_empty())) { CheckFailed("invalid uses of intrinsic global variable" , &GV); return; } } while (false); | ||||
| 791 | |||||
| 792 | Type *GVType = GV.getValueType(); | ||||
| 793 | if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) { | ||||
| 794 | PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType()); | ||||
| 795 | Check(PTy, "wrong type for intrinsic global variable", &GV)do { if (!(PTy)) { CheckFailed("wrong type for intrinsic global variable" , &GV); return; } } while (false); | ||||
| 796 | if (GV.hasInitializer()) { | ||||
| 797 | const Constant *Init = GV.getInitializer(); | ||||
| 798 | const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init); | ||||
| 799 | Check(InitArray, "wrong initalizer for intrinsic global variable",do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false) | ||||
| 800 | Init)do { if (!(InitArray)) { CheckFailed("wrong initalizer for intrinsic global variable" , Init); return; } } while (false); | ||||
| 801 | for (Value *Op : InitArray->operands()) { | ||||
| 802 | Value *V = Op->stripPointerCasts(); | ||||
| 803 | Check(isa<GlobalVariable>(V) || isa<Function>(V) ||do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false) | ||||
| 804 | isa<GlobalAlias>(V),do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false) | ||||
| 805 | Twine("invalid ") + GV.getName() + " member", V)do { if (!(isa<GlobalVariable>(V) || isa<Function> (V) || isa<GlobalAlias>(V))) { CheckFailed(Twine("invalid " ) + GV.getName() + " member", V); return; } } while (false); | ||||
| 806 | Check(V->hasName(),do { if (!(V->hasName())) { CheckFailed(Twine("members of " ) + GV.getName() + " must be named", V); return; } } while (false ) | ||||
| 807 | Twine("members of ") + GV.getName() + " must be named", V)do { if (!(V->hasName())) { CheckFailed(Twine("members of " ) + GV.getName() + " must be named", V); return; } } while (false ); | ||||
| 808 | } | ||||
| 809 | } | ||||
| 810 | } | ||||
| 811 | } | ||||
| 812 | |||||
| 813 | // Visit any debug info attachments. | ||||
| 814 | SmallVector<MDNode *, 1> MDs; | ||||
| 815 | GV.getMetadata(LLVMContext::MD_dbg, MDs); | ||||
| 816 | for (auto *MD : MDs) { | ||||
| 817 | if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD)) | ||||
| 818 | visitDIGlobalVariableExpression(*GVE); | ||||
| 819 | else | ||||
| 820 | CheckDI(false, "!dbg attachment of global variable must be a "do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false) | ||||
| 821 | "DIGlobalVariableExpression")do { if (!(false)) { DebugInfoCheckFailed("!dbg attachment of global variable must be a " "DIGlobalVariableExpression"); return; } } while (false); | ||||
| 822 | } | ||||
| 823 | |||||
| 824 | // Scalable vectors cannot be global variables, since we don't know | ||||
| 825 | // the runtime size. If the global is an array containing scalable vectors, | ||||
| 826 | // that will be caught by the isValidElementType methods in StructType or | ||||
| 827 | // ArrayType instead. | ||||
| 828 | Check(!isa<ScalableVectorType>(GV.getValueType()),do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false) | ||||
| 829 | "Globals cannot contain scalable vectors", &GV)do { if (!(!isa<ScalableVectorType>(GV.getValueType())) ) { CheckFailed("Globals cannot contain scalable vectors", & GV); return; } } while (false); | ||||
| 830 | |||||
| 831 | if (auto *STy = dyn_cast<StructType>(GV.getValueType())) | ||||
| 832 | Check(!STy->containsScalableVectorType(),do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false) | ||||
| 833 | "Globals cannot contain scalable vectors", &GV)do { if (!(!STy->containsScalableVectorType())) { CheckFailed ("Globals cannot contain scalable vectors", &GV); return; } } while (false); | ||||
| 834 | |||||
| 835 | // Check if it's a target extension type that disallows being used as a | ||||
| 836 | // global. | ||||
| 837 | if (auto *TTy = dyn_cast<TargetExtType>(GV.getValueType())) | ||||
| 838 | Check(TTy->hasProperty(TargetExtType::CanBeGlobal),do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false) | ||||
| 839 | "Global @" + GV.getName() + " has illegal target extension type",do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false) | ||||
| 840 | TTy)do { if (!(TTy->hasProperty(TargetExtType::CanBeGlobal))) { CheckFailed("Global @" + GV.getName() + " has illegal target extension type" , TTy); return; } } while (false); | ||||
| 841 | |||||
| 842 | if (!GV.hasInitializer()) { | ||||
| 843 | visitGlobalValue(GV); | ||||
| 844 | return; | ||||
| 845 | } | ||||
| 846 | |||||
| 847 | // Walk any aggregate initializers looking for bitcasts between address spaces | ||||
| 848 | visitConstantExprsRecursively(GV.getInitializer()); | ||||
| 849 | |||||
| 850 | visitGlobalValue(GV); | ||||
| 851 | } | ||||
| 852 | |||||
| 853 | void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { | ||||
| 854 | SmallPtrSet<const GlobalAlias*, 4> Visited; | ||||
| 855 | Visited.insert(&GA); | ||||
| 856 | visitAliaseeSubExpr(Visited, GA, C); | ||||
| 857 | } | ||||
| 858 | |||||
| 859 | void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited, | ||||
| 860 | const GlobalAlias &GA, const Constant &C) { | ||||
| 861 | if (GA.hasAvailableExternallyLinkage()) { | ||||
| 862 | Check(isa<GlobalValue>(C) &&do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
| 863 | cast<GlobalValue>(C).hasAvailableExternallyLinkage(),do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
| 864 | "available_externally alias must point to available_externally "do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
| 865 | "global value",do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false) | ||||
| 866 | &GA)do { if (!(isa<GlobalValue>(C) && cast<GlobalValue >(C).hasAvailableExternallyLinkage())) { CheckFailed("available_externally alias must point to available_externally " "global value", &GA); return; } } while (false); | ||||
| 867 | } | ||||
| 868 | if (const auto *GV = dyn_cast<GlobalValue>(&C)) { | ||||
| 869 | if (!GA.hasAvailableExternallyLinkage()) { | ||||
| 870 | Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false) | ||||
| 871 | &GA)do { if (!(!GV->isDeclarationForLinker())) { CheckFailed("Alias must point to a definition" , &GA); return; } } while (false); | ||||
| 872 | } | ||||
| 873 | |||||
| 874 | if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) { | ||||
| 875 | Check(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA)do { if (!(Visited.insert(GA2).second)) { CheckFailed("Aliases cannot form a cycle" , &GA); return; } } while (false); | ||||
| 876 | |||||
| 877 | Check(!GA2->isInterposable(),do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false) | ||||
| 878 | "Alias cannot point to an interposable alias", &GA)do { if (!(!GA2->isInterposable())) { CheckFailed("Alias cannot point to an interposable alias" , &GA); return; } } while (false); | ||||
| 879 | } else { | ||||
| 880 | // Only continue verifying subexpressions of GlobalAliases. | ||||
| 881 | // Do not recurse into global initializers. | ||||
| 882 | return; | ||||
| 883 | } | ||||
| 884 | } | ||||
| 885 | |||||
| 886 | if (const auto *CE = dyn_cast<ConstantExpr>(&C)) | ||||
| 887 | visitConstantExprsRecursively(CE); | ||||
| 888 | |||||
| 889 | for (const Use &U : C.operands()) { | ||||
| 890 | Value *V = &*U; | ||||
| 891 | if (const auto *GA2 = dyn_cast<GlobalAlias>(V)) | ||||
| 892 | visitAliaseeSubExpr(Visited, GA, *GA2->getAliasee()); | ||||
| 893 | else if (const auto *C2 = dyn_cast<Constant>(V)) | ||||
| 894 | visitAliaseeSubExpr(Visited, GA, *C2); | ||||
| 895 | } | ||||
| 896 | } | ||||
| 897 | |||||
| 898 | void Verifier::visitGlobalAlias(const GlobalAlias &GA) { | ||||
| 899 | Check(GlobalAlias::isValidLinkage(GA.getLinkage()),do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
| 900 | "Alias should have private, internal, linkonce, weak, linkonce_odr, "do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
| 901 | "weak_odr, external, or available_externally linkage!",do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false) | ||||
| 902 | &GA)do { if (!(GlobalAlias::isValidLinkage(GA.getLinkage()))) { CheckFailed ("Alias should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, external, or available_externally linkage!", & GA); return; } } while (false); | ||||
| 903 | const Constant *Aliasee = GA.getAliasee(); | ||||
| 904 | Check(Aliasee, "Aliasee cannot be NULL!", &GA)do { if (!(Aliasee)) { CheckFailed("Aliasee cannot be NULL!", &GA); return; } } while (false); | ||||
| 905 | Check(GA.getType() == Aliasee->getType(),do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false) | ||||
| 906 | "Alias and aliasee types should match!", &GA)do { if (!(GA.getType() == Aliasee->getType())) { CheckFailed ("Alias and aliasee types should match!", &GA); return; } } while (false); | ||||
| 907 | |||||
| 908 | Check(isa<GlobalValue>(Aliasee) || isa<ConstantExpr>(Aliasee),do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false) | ||||
| 909 | "Aliasee should be either GlobalValue or ConstantExpr", &GA)do { if (!(isa<GlobalValue>(Aliasee) || isa<ConstantExpr >(Aliasee))) { CheckFailed("Aliasee should be either GlobalValue or ConstantExpr" , &GA); return; } } while (false); | ||||
| 910 | |||||
| 911 | visitAliaseeSubExpr(GA, *Aliasee); | ||||
| 912 | |||||
| 913 | visitGlobalValue(GA); | ||||
| 914 | } | ||||
| 915 | |||||
| 916 | void Verifier::visitGlobalIFunc(const GlobalIFunc &GI) { | ||||
| 917 | Check(GlobalIFunc::isValidLinkage(GI.getLinkage()),do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
| 918 | "IFunc should have private, internal, linkonce, weak, linkonce_odr, "do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
| 919 | "weak_odr, or external linkage!",do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false) | ||||
| 920 | &GI)do { if (!(GlobalIFunc::isValidLinkage(GI.getLinkage()))) { CheckFailed ("IFunc should have private, internal, linkonce, weak, linkonce_odr, " "weak_odr, or external linkage!", &GI); return; } } while (false); | ||||
| 921 | // Pierce through ConstantExprs and GlobalAliases and check that the resolver | ||||
| 922 | // is a Function definition. | ||||
| 923 | const Function *Resolver = GI.getResolverFunction(); | ||||
| 924 | Check(Resolver, "IFunc must have a Function resolver", &GI)do { if (!(Resolver)) { CheckFailed("IFunc must have a Function resolver" , &GI); return; } } while (false); | ||||
| 925 | Check(!Resolver->isDeclarationForLinker(),do { if (!(!Resolver->isDeclarationForLinker())) { CheckFailed ("IFunc resolver must be a definition", &GI); return; } } while (false) | ||||
| 926 | "IFunc resolver must be a definition", &GI)do { if (!(!Resolver->isDeclarationForLinker())) { CheckFailed ("IFunc resolver must be a definition", &GI); return; } } while (false); | ||||
| 927 | |||||
| 928 | // Check that the immediate resolver operand (prior to any bitcasts) has the | ||||
| 929 | // correct type. | ||||
| 930 | const Type *ResolverTy = GI.getResolver()->getType(); | ||||
| 931 | |||||
| 932 | Check(isa<PointerType>(Resolver->getFunctionType()->getReturnType()),do { if (!(isa<PointerType>(Resolver->getFunctionType ()->getReturnType()))) { CheckFailed("IFunc resolver must return a pointer" , &GI); return; } } while (false) | ||||
| 933 | "IFunc resolver must return a pointer", &GI)do { if (!(isa<PointerType>(Resolver->getFunctionType ()->getReturnType()))) { CheckFailed("IFunc resolver must return a pointer" , &GI); return; } } while (false); | ||||
| 934 | |||||
| 935 | const Type *ResolverFuncTy = | ||||
| 936 | GlobalIFunc::getResolverFunctionType(GI.getValueType()); | ||||
| 937 | Check(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace()),do { if (!(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace ()))) { CheckFailed("IFunc resolver has incorrect type", & GI); return; } } while (false) | ||||
| 938 | "IFunc resolver has incorrect type", &GI)do { if (!(ResolverTy == ResolverFuncTy->getPointerTo(GI.getAddressSpace ()))) { CheckFailed("IFunc resolver has incorrect type", & GI); return; } } while (false); | ||||
| 939 | } | ||||
| 940 | |||||
| 941 | void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { | ||||
| 942 | // There used to be various other llvm.dbg.* nodes, but we don't support | ||||
| 943 | // upgrading them and we want to reserve the namespace for future uses. | ||||
| 944 | if (NMD.getName().startswith("llvm.dbg.")) | ||||
| 945 | CheckDI(NMD.getName() == "llvm.dbg.cu",do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false) | ||||
| 946 | "unrecognized named metadata node in the llvm.dbg namespace", &NMD)do { if (!(NMD.getName() == "llvm.dbg.cu")) { DebugInfoCheckFailed ("unrecognized named metadata node in the llvm.dbg namespace" , &NMD); return; } } while (false); | ||||
| 947 | for (const MDNode *MD : NMD.operands()) { | ||||
| 948 | if (NMD.getName() == "llvm.dbg.cu") | ||||
| 949 | CheckDI(MD && isa<DICompileUnit>(MD), "invalid compile unit", &NMD, MD)do { if (!(MD && isa<DICompileUnit>(MD))) { DebugInfoCheckFailed ("invalid compile unit", &NMD, MD); return; } } while (false ); | ||||
| 950 | |||||
| 951 | if (!MD) | ||||
| 952 | continue; | ||||
| 953 | |||||
| 954 | visitMDNode(*MD, AreDebugLocsAllowed::Yes); | ||||
| 955 | } | ||||
| 956 | } | ||||
| 957 | |||||
| 958 | void Verifier::visitMDNode(const MDNode &MD, AreDebugLocsAllowed AllowLocs) { | ||||
| 959 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
| 960 | // avoids infinite recursion here, as well as being an optimization. | ||||
| 961 | if (!MDNodes.insert(&MD).second) | ||||
| 962 | return; | ||||
| 963 | |||||
| 964 | Check(&MD.getContext() == &Context,do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false) | ||||
| 965 | "MDNode context does not match Module context!", &MD)do { if (!(&MD.getContext() == &Context)) { CheckFailed ("MDNode context does not match Module context!", &MD); return ; } } while (false); | ||||
| 966 | |||||
| 967 | switch (MD.getMetadataID()) { | ||||
| 968 | default: | ||||
| 969 | llvm_unreachable("Invalid MDNode subclass")::llvm::llvm_unreachable_internal("Invalid MDNode subclass", "llvm/lib/IR/Verifier.cpp" , 969); | ||||
| 970 | case Metadata::MDTupleKind: | ||||
| 971 | break; | ||||
| 972 | #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) \ | ||||
| 973 | case Metadata::CLASS##Kind: \ | ||||
| 974 | visit##CLASS(cast<CLASS>(MD)); \ | ||||
| 975 | break; | ||||
| 976 | #include "llvm/IR/Metadata.def" | ||||
| 977 | } | ||||
| 978 | |||||
| 979 | for (const Metadata *Op : MD.operands()) { | ||||
| 980 | if (!Op) | ||||
| 981 | continue; | ||||
| 982 | Check(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false) | ||||
| 983 | &MD, Op)do { if (!(!isa<LocalAsMetadata>(Op))) { CheckFailed("Invalid operand for global metadata!" , &MD, Op); return; } } while (false); | ||||
| 984 | CheckDI(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed::Yes,do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false) | ||||
| 985 | "DILocation not allowed within this metadata node", &MD, Op)do { if (!(!isa<DILocation>(Op) || AllowLocs == AreDebugLocsAllowed ::Yes)) { DebugInfoCheckFailed("DILocation not allowed within this metadata node" , &MD, Op); return; } } while (false); | ||||
| 986 | if (auto *N = dyn_cast<MDNode>(Op)) { | ||||
| 987 | visitMDNode(*N, AllowLocs); | ||||
| 988 | continue; | ||||
| 989 | } | ||||
| 990 | if (auto *V = dyn_cast<ValueAsMetadata>(Op)) { | ||||
| 991 | visitValueAsMetadata(*V, nullptr); | ||||
| 992 | continue; | ||||
| 993 | } | ||||
| 994 | } | ||||
| 995 | |||||
| 996 | // Check these last, so we diagnose problems in operands first. | ||||
| 997 | Check(!MD.isTemporary(), "Expected no forward declarations!", &MD)do { if (!(!MD.isTemporary())) { CheckFailed("Expected no forward declarations!" , &MD); return; } } while (false); | ||||
| 998 | Check(MD.isResolved(), "All nodes should be resolved!", &MD)do { if (!(MD.isResolved())) { CheckFailed("All nodes should be resolved!" , &MD); return; } } while (false); | ||||
| 999 | } | ||||
| 1000 | |||||
| 1001 | void Verifier::visitValueAsMetadata(const ValueAsMetadata &MD, Function *F) { | ||||
| 1002 | Check(MD.getValue(), "Expected valid value", &MD)do { if (!(MD.getValue())) { CheckFailed("Expected valid value" , &MD); return; } } while (false); | ||||
| 1003 | Check(!MD.getValue()->getType()->isMetadataTy(),do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false) | ||||
| 1004 | "Unexpected metadata round-trip through values", &MD, MD.getValue())do { if (!(!MD.getValue()->getType()->isMetadataTy())) { CheckFailed("Unexpected metadata round-trip through values", &MD, MD.getValue()); return; } } while (false); | ||||
| 1005 | |||||
| 1006 | auto *L = dyn_cast<LocalAsMetadata>(&MD); | ||||
| 1007 | if (!L) | ||||
| 1008 | return; | ||||
| 1009 | |||||
| 1010 | Check(F, "function-local metadata used outside a function", L)do { if (!(F)) { CheckFailed("function-local metadata used outside a function" , L); return; } } while (false); | ||||
| 1011 | |||||
| 1012 | // If this was an instruction, bb, or argument, verify that it is in the | ||||
| 1013 | // function that we expect. | ||||
| 1014 | Function *ActualF = nullptr; | ||||
| 1015 | if (Instruction *I = dyn_cast<Instruction>(L->getValue())) { | ||||
| 1016 | Check(I->getParent(), "function-local metadata not in basic block", L, I)do { if (!(I->getParent())) { CheckFailed("function-local metadata not in basic block" , L, I); return; } } while (false); | ||||
| 1017 | ActualF = I->getParent()->getParent(); | ||||
| 1018 | } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue())) | ||||
| 1019 | ActualF = BB->getParent(); | ||||
| 1020 | else if (Argument *A = dyn_cast<Argument>(L->getValue())) | ||||
| 1021 | ActualF = A->getParent(); | ||||
| 1022 | assert(ActualF && "Unimplemented function local metadata case!")(static_cast <bool> (ActualF && "Unimplemented function local metadata case!" ) ? void (0) : __assert_fail ("ActualF && \"Unimplemented function local metadata case!\"" , "llvm/lib/IR/Verifier.cpp", 1022, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 1023 | |||||
| 1024 | Check(ActualF == F, "function-local metadata used in wrong function", L)do { if (!(ActualF == F)) { CheckFailed("function-local metadata used in wrong function" , L); return; } } while (false); | ||||
| 1025 | } | ||||
| 1026 | |||||
| 1027 | void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) { | ||||
| 1028 | Metadata *MD = MDV.getMetadata(); | ||||
| 1029 | if (auto *N = dyn_cast<MDNode>(MD)) { | ||||
| 1030 | visitMDNode(*N, AreDebugLocsAllowed::No); | ||||
| 1031 | return; | ||||
| 1032 | } | ||||
| 1033 | |||||
| 1034 | // Only visit each node once. Metadata can be mutually recursive, so this | ||||
| 1035 | // avoids infinite recursion here, as well as being an optimization. | ||||
| 1036 | if (!MDNodes.insert(MD).second) | ||||
| 1037 | return; | ||||
| 1038 | |||||
| 1039 | if (auto *V = dyn_cast<ValueAsMetadata>(MD)) | ||||
| 1040 | visitValueAsMetadata(*V, F); | ||||
| 1041 | } | ||||
| 1042 | |||||
| 1043 | static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); } | ||||
| 1044 | static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); } | ||||
| 1045 | static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); } | ||||
| 1046 | |||||
| 1047 | void Verifier::visitDILocation(const DILocation &N) { | ||||
| 1048 | CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1049 | "location requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("location requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1050 | if (auto *IA = N.getRawInlinedAt()) | ||||
| 1051 | CheckDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA)do { if (!(isa<DILocation>(IA))) { DebugInfoCheckFailed ("inlined-at should be a location", &N, IA); return; } } while (false); | ||||
| 1052 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
| 1053 | CheckDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
| 1054 | } | ||||
| 1055 | |||||
| 1056 | void Verifier::visitGenericDINode(const GenericDINode &N) { | ||||
| 1057 | CheckDI(N.getTag(), "invalid tag", &N)do { if (!(N.getTag())) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1058 | } | ||||
| 1059 | |||||
| 1060 | void Verifier::visitDIScope(const DIScope &N) { | ||||
| 1061 | if (auto *F = N.getRawFile()) | ||||
| 1062 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1063 | } | ||||
| 1064 | |||||
| 1065 | void Verifier::visitDISubrange(const DISubrange &N) { | ||||
| 1066 | CheckDI(N.getTag() == dwarf::DW_TAG_subrange_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1067 | bool HasAssumedSizedArraySupport = dwarf::isFortran(CurrentSourceLang); | ||||
| 1068 | CheckDI(HasAssumedSizedArraySupport || N.getRawCountNode() ||do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
| 1069 | N.getRawUpperBound(),do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false) | ||||
| 1070 | "Subrange must contain count or upperBound", &N)do { if (!(HasAssumedSizedArraySupport || N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed("Subrange must contain count or upperBound" , &N); return; } } while (false); | ||||
| 1071 | CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false) | ||||
| 1072 | "Subrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("Subrange can have any one of count or upperBound", &N); return; } } while (false); | ||||
| 1073 | auto *CBound = N.getRawCountNode(); | ||||
| 1074 | CheckDI(!CBound || isa<ConstantAsMetadata>(CBound) ||do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1075 | isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1076 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<ConstantAsMetadata>(CBound) || isa<DIVariable>(CBound) || isa<DIExpression>(CBound ))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1077 | auto Count = N.getCount(); | ||||
| 1078 | CheckDI(!Count || !isa<ConstantInt *>(Count) ||do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
| 1079 | cast<ConstantInt *>(Count)->getSExtValue() >= -1,do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false) | ||||
| 1080 | "invalid subrange count", &N)do { if (!(!Count || !isa<ConstantInt *>(Count) || cast <ConstantInt *>(Count)->getSExtValue() >= -1)) { DebugInfoCheckFailed ("invalid subrange count", &N); return; } } while (false); | ||||
| 1081 | auto *LBound = N.getRawLowerBound(); | ||||
| 1082 | CheckDI(!LBound || isa<ConstantAsMetadata>(LBound) ||do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1083 | isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1084 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1085 | &N)do { if (!(!LBound || isa<ConstantAsMetadata>(LBound) || isa<DIVariable>(LBound) || isa<DIExpression>(LBound ))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1086 | auto *UBound = N.getRawUpperBound(); | ||||
| 1087 | CheckDI(!UBound || isa<ConstantAsMetadata>(UBound) ||do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1088 | isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1089 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1090 | &N)do { if (!(!UBound || isa<ConstantAsMetadata>(UBound) || isa<DIVariable>(UBound) || isa<DIExpression>(UBound ))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1091 | auto *Stride = N.getRawStride(); | ||||
| 1092 | CheckDI(!Stride || isa<ConstantAsMetadata>(Stride) ||do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1093 | isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1094 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(!Stride || isa<ConstantAsMetadata>(Stride) || isa<DIVariable>(Stride) || isa<DIExpression>(Stride ))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1095 | } | ||||
| 1096 | |||||
| 1097 | void Verifier::visitDIGenericSubrange(const DIGenericSubrange &N) { | ||||
| 1098 | CheckDI(N.getTag() == dwarf::DW_TAG_generic_subrange, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_generic_subrange)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1099 | CheckDI(N.getRawCountNode() || N.getRawUpperBound(),do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false) | ||||
| 1100 | "GenericSubrange must contain count or upperBound", &N)do { if (!(N.getRawCountNode() || N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange must contain count or upperBound", &N); return; } } while (false); | ||||
| 1101 | CheckDI(!N.getRawCountNode() || !N.getRawUpperBound(),do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false) | ||||
| 1102 | "GenericSubrange can have any one of count or upperBound", &N)do { if (!(!N.getRawCountNode() || !N.getRawUpperBound())) { DebugInfoCheckFailed ("GenericSubrange can have any one of count or upperBound", & N); return; } } while (false); | ||||
| 1103 | auto *CBound = N.getRawCountNode(); | ||||
| 1104 | CheckDI(!CBound || isa<DIVariable>(CBound) || isa<DIExpression>(CBound),do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1105 | "Count must be signed constant or DIVariable or DIExpression", &N)do { if (!(!CBound || isa<DIVariable>(CBound) || isa< DIExpression>(CBound))) { DebugInfoCheckFailed("Count must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1106 | auto *LBound = N.getRawLowerBound(); | ||||
| 1107 | CheckDI(LBound, "GenericSubrange must contain lowerBound", &N)do { if (!(LBound)) { DebugInfoCheckFailed("GenericSubrange must contain lowerBound" , &N); return; } } while (false); | ||||
| 1108 | CheckDI(isa<DIVariable>(LBound) || isa<DIExpression>(LBound),do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1109 | "LowerBound must be signed constant or DIVariable or DIExpression",do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1110 | &N)do { if (!(isa<DIVariable>(LBound) || isa<DIExpression >(LBound))) { DebugInfoCheckFailed("LowerBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1111 | auto *UBound = N.getRawUpperBound(); | ||||
| 1112 | CheckDI(!UBound || isa<DIVariable>(UBound) || isa<DIExpression>(UBound),do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1113 | "UpperBound must be signed constant or DIVariable or DIExpression",do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1114 | &N)do { if (!(!UBound || isa<DIVariable>(UBound) || isa< DIExpression>(UBound))) { DebugInfoCheckFailed("UpperBound must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1115 | auto *Stride = N.getRawStride(); | ||||
| 1116 | CheckDI(Stride, "GenericSubrange must contain stride", &N)do { if (!(Stride)) { DebugInfoCheckFailed("GenericSubrange must contain stride" , &N); return; } } while (false); | ||||
| 1117 | CheckDI(isa<DIVariable>(Stride) || isa<DIExpression>(Stride),do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false) | ||||
| 1118 | "Stride must be signed constant or DIVariable or DIExpression", &N)do { if (!(isa<DIVariable>(Stride) || isa<DIExpression >(Stride))) { DebugInfoCheckFailed("Stride must be signed constant or DIVariable or DIExpression" , &N); return; } } while (false); | ||||
| 1119 | } | ||||
| 1120 | |||||
| 1121 | void Verifier::visitDIEnumerator(const DIEnumerator &N) { | ||||
| 1122 | CheckDI(N.getTag() == dwarf::DW_TAG_enumerator, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_enumerator)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1123 | } | ||||
| 1124 | |||||
| 1125 | void Verifier::visitDIBasicType(const DIBasicType &N) { | ||||
| 1126 | CheckDI(N.getTag() == dwarf::DW_TAG_base_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1127 | N.getTag() == dwarf::DW_TAG_unspecified_type ||do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1128 | N.getTag() == dwarf::DW_TAG_string_type,do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1129 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_base_type || N.getTag( ) == dwarf::DW_TAG_unspecified_type || N.getTag() == dwarf::DW_TAG_string_type )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1130 | } | ||||
| 1131 | |||||
| 1132 | void Verifier::visitDIStringType(const DIStringType &N) { | ||||
| 1133 | CheckDI(N.getTag() == dwarf::DW_TAG_string_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_string_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1134 | CheckDI(!(N.isBigEndian() && N.isLittleEndian()), "has conflicting flags",do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false) | ||||
| 1135 | &N)do { if (!(!(N.isBigEndian() && N.isLittleEndian()))) { DebugInfoCheckFailed("has conflicting flags", &N); return ; } } while (false); | ||||
| 1136 | } | ||||
| 1137 | |||||
| 1138 | void Verifier::visitDIDerivedType(const DIDerivedType &N) { | ||||
| 1139 | // Common scope checks. | ||||
| 1140 | visitDIScope(N); | ||||
| 1141 | |||||
| 1142 | CheckDI(N.getTag() == dwarf::DW_TAG_typedef ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1143 | N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1144 | N.getTag() == dwarf::DW_TAG_ptr_to_member_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1145 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1146 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1147 | N.getTag() == dwarf::DW_TAG_const_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1148 | N.getTag() == dwarf::DW_TAG_immutable_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1149 | N.getTag() == dwarf::DW_TAG_volatile_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1150 | N.getTag() == dwarf::DW_TAG_restrict_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1151 | N.getTag() == dwarf::DW_TAG_atomic_type ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1152 | N.getTag() == dwarf::DW_TAG_member ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1153 | N.getTag() == dwarf::DW_TAG_inheritance ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1154 | N.getTag() == dwarf::DW_TAG_friend ||do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1155 | N.getTag() == dwarf::DW_TAG_set_type,do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1156 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_typedef || N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag() == dwarf::DW_TAG_ptr_to_member_type || N.getTag() == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type || N.getTag() == dwarf:: DW_TAG_const_type || N.getTag() == dwarf::DW_TAG_immutable_type || N.getTag() == dwarf::DW_TAG_volatile_type || N.getTag() == dwarf::DW_TAG_restrict_type || N.getTag() == dwarf::DW_TAG_atomic_type || N.getTag() == dwarf::DW_TAG_member || N.getTag() == dwarf ::DW_TAG_inheritance || N.getTag() == dwarf::DW_TAG_friend || N.getTag() == dwarf::DW_TAG_set_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1157 | if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) { | ||||
| 1158 | CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false) | ||||
| 1159 | N.getRawExtraData())do { if (!(isType(N.getRawExtraData()))) { DebugInfoCheckFailed ("invalid pointer to member type", &N, N.getRawExtraData( )); return; } } while (false); | ||||
| 1160 | } | ||||
| 1161 | |||||
| 1162 | if (N.getTag() == dwarf::DW_TAG_set_type) { | ||||
| 1163 | if (auto *T = N.getRawBaseType()) { | ||||
| 1164 | auto *Enum = dyn_cast_or_null<DICompositeType>(T); | ||||
| 1165 | auto *Basic = dyn_cast_or_null<DIBasicType>(T); | ||||
| 1166 | CheckDI(do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1167 | (Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1168 | (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1169 | Basic->getEncoding() == dwarf::DW_ATE_signed ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1170 | Basic->getEncoding() == dwarf::DW_ATE_unsigned_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1171 | Basic->getEncoding() == dwarf::DW_ATE_signed_char ||do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1172 | Basic->getEncoding() == dwarf::DW_ATE_boolean)),do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false) | ||||
| 1173 | "invalid set base type", &N, T)do { if (!((Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type ) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic-> getEncoding() == dwarf::DW_ATE_unsigned_char || Basic->getEncoding () == dwarf::DW_ATE_signed_char || Basic->getEncoding() == dwarf::DW_ATE_boolean)))) { DebugInfoCheckFailed("invalid set base type" , &N, T); return; } } while (false); | ||||
| 1174 | } | ||||
| 1175 | } | ||||
| 1176 | |||||
| 1177 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1178 | CheckDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
| 1179 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
| 1180 | |||||
| 1181 | if (N.getDWARFAddressSpace()) { | ||||
| 1182 | CheckDI(N.getTag() == dwarf::DW_TAG_pointer_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1183 | N.getTag() == dwarf::DW_TAG_reference_type ||do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1184 | N.getTag() == dwarf::DW_TAG_rvalue_reference_type,do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1185 | "DWARF address space only applies to pointer or reference types",do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false) | ||||
| 1186 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_pointer_type || N.getTag () == dwarf::DW_TAG_reference_type || N.getTag() == dwarf::DW_TAG_rvalue_reference_type )) { DebugInfoCheckFailed("DWARF address space only applies to pointer or reference types" , &N); return; } } while (false); | ||||
| 1187 | } | ||||
| 1188 | } | ||||
| 1189 | |||||
| 1190 | /// Detect mutually exclusive flags. | ||||
| 1191 | static bool hasConflictingReferenceFlags(unsigned Flags) { | ||||
| 1192 | return ((Flags & DINode::FlagLValueReference) && | ||||
| 1193 | (Flags & DINode::FlagRValueReference)) || | ||||
| 1194 | ((Flags & DINode::FlagTypePassByValue) && | ||||
| 1195 | (Flags & DINode::FlagTypePassByReference)); | ||||
| 1196 | } | ||||
| 1197 | |||||
| 1198 | void Verifier::visitTemplateParams(const MDNode &N, const Metadata &RawParams) { | ||||
| 1199 | auto *Params = dyn_cast<MDTuple>(&RawParams); | ||||
| 1200 | CheckDI(Params, "invalid template params", &N, &RawParams)do { if (!(Params)) { DebugInfoCheckFailed("invalid template params" , &N, &RawParams); return; } } while (false); | ||||
| 1201 | for (Metadata *Op : Params->operands()) { | ||||
| 1202 | CheckDI(Op && isa<DITemplateParameter>(Op), "invalid template parameter",do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false) | ||||
| 1203 | &N, Params, Op)do { if (!(Op && isa<DITemplateParameter>(Op))) { DebugInfoCheckFailed("invalid template parameter", &N, Params, Op); return; } } while (false); | ||||
| 1204 | } | ||||
| 1205 | } | ||||
| 1206 | |||||
| 1207 | void Verifier::visitDICompositeType(const DICompositeType &N) { | ||||
| 1208 | // Common scope checks. | ||||
| 1209 | visitDIScope(N); | ||||
| 1210 | |||||
| 1211 | CheckDI(N.getTag() == dwarf::DW_TAG_array_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1212 | N.getTag() == dwarf::DW_TAG_structure_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1213 | N.getTag() == dwarf::DW_TAG_union_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1214 | N.getTag() == dwarf::DW_TAG_enumeration_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1215 | N.getTag() == dwarf::DW_TAG_class_type ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1216 | N.getTag() == dwarf::DW_TAG_variant_part ||do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1217 | N.getTag() == dwarf::DW_TAG_namelist,do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1218 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_array_type || N.getTag () == dwarf::DW_TAG_structure_type || N.getTag() == dwarf::DW_TAG_union_type || N.getTag() == dwarf::DW_TAG_enumeration_type || N.getTag( ) == dwarf::DW_TAG_class_type || N.getTag() == dwarf::DW_TAG_variant_part || N.getTag() == dwarf::DW_TAG_namelist)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1219 | |||||
| 1220 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1221 | CheckDI(isType(N.getRawBaseType()), "invalid base type", &N,do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false) | ||||
| 1222 | N.getRawBaseType())do { if (!(isType(N.getRawBaseType()))) { DebugInfoCheckFailed ("invalid base type", &N, N.getRawBaseType()); return; } } while (false); | ||||
| 1223 | |||||
| 1224 | CheckDI(!N.getRawElements() || isa<MDTuple>(N.getRawElements()),do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false) | ||||
| 1225 | "invalid composite elements", &N, N.getRawElements())do { if (!(!N.getRawElements() || isa<MDTuple>(N.getRawElements ()))) { DebugInfoCheckFailed("invalid composite elements", & N, N.getRawElements()); return; } } while (false); | ||||
| 1226 | CheckDI(isType(N.getRawVTableHolder()), "invalid vtable holder", &N,do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false) | ||||
| 1227 | N.getRawVTableHolder())do { if (!(isType(N.getRawVTableHolder()))) { DebugInfoCheckFailed ("invalid vtable holder", &N, N.getRawVTableHolder()); return ; } } while (false); | ||||
| 1228 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1229 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1230 | unsigned DIBlockByRefStruct = 1 << 4; | ||||
| 1231 | CheckDI((N.getFlags() & DIBlockByRefStruct) == 0,do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false) | ||||
| 1232 | "DIBlockByRefStruct on DICompositeType is no longer supported", &N)do { if (!((N.getFlags() & DIBlockByRefStruct) == 0)) { DebugInfoCheckFailed ("DIBlockByRefStruct on DICompositeType is no longer supported" , &N); return; } } while (false); | ||||
| 1233 | |||||
| 1234 | if (N.isVector()) { | ||||
| 1235 | const DINodeArray Elements = N.getElements(); | ||||
| 1236 | CheckDI(Elements.size() == 1 &&do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
| 1237 | Elements[0]->getTag() == dwarf::DW_TAG_subrange_type,do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false) | ||||
| 1238 | "invalid vector, expected one element of type subrange", &N)do { if (!(Elements.size() == 1 && Elements[0]->getTag () == dwarf::DW_TAG_subrange_type)) { DebugInfoCheckFailed("invalid vector, expected one element of type subrange" , &N); return; } } while (false); | ||||
| 1239 | } | ||||
| 1240 | |||||
| 1241 | if (auto *Params = N.getRawTemplateParams()) | ||||
| 1242 | visitTemplateParams(N, *Params); | ||||
| 1243 | |||||
| 1244 | if (auto *D = N.getRawDiscriminator()) { | ||||
| 1245 | CheckDI(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part,do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false) | ||||
| 1246 | "discriminator can only appear on variant part")do { if (!(isa<DIDerivedType>(D) && N.getTag() == dwarf::DW_TAG_variant_part)) { DebugInfoCheckFailed("discriminator can only appear on variant part" ); return; } } while (false); | ||||
| 1247 | } | ||||
| 1248 | |||||
| 1249 | if (N.getRawDataLocation()) { | ||||
| 1250 | CheckDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false) | ||||
| 1251 | "dataLocation can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("dataLocation can only appear in array type"); return; } } while (false); | ||||
| 1252 | } | ||||
| 1253 | |||||
| 1254 | if (N.getRawAssociated()) { | ||||
| 1255 | CheckDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false) | ||||
| 1256 | "associated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("associated can only appear in array type"); return; } } while (false); | ||||
| 1257 | } | ||||
| 1258 | |||||
| 1259 | if (N.getRawAllocated()) { | ||||
| 1260 | CheckDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false) | ||||
| 1261 | "allocated can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("allocated can only appear in array type"); return; } } while (false); | ||||
| 1262 | } | ||||
| 1263 | |||||
| 1264 | if (N.getRawRank()) { | ||||
| 1265 | CheckDI(N.getTag() == dwarf::DW_TAG_array_type,do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ) | ||||
| 1266 | "rank can only appear in array type")do { if (!(N.getTag() == dwarf::DW_TAG_array_type)) { DebugInfoCheckFailed ("rank can only appear in array type"); return; } } while (false ); | ||||
| 1267 | } | ||||
| 1268 | } | ||||
| 1269 | |||||
| 1270 | void Verifier::visitDISubroutineType(const DISubroutineType &N) { | ||||
| 1271 | CheckDI(N.getTag() == dwarf::DW_TAG_subroutine_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subroutine_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1272 | if (auto *Types = N.getRawTypeArray()) { | ||||
| 1273 | CheckDI(isa<MDTuple>(Types), "invalid composite elements", &N, Types)do { if (!(isa<MDTuple>(Types))) { DebugInfoCheckFailed ("invalid composite elements", &N, Types); return; } } while (false); | ||||
| 1274 | for (Metadata *Ty : N.getTypeArray()->operands()) { | ||||
| 1275 | CheckDI(isType(Ty), "invalid subroutine type ref", &N, Types, Ty)do { if (!(isType(Ty))) { DebugInfoCheckFailed("invalid subroutine type ref" , &N, Types, Ty); return; } } while (false); | ||||
| 1276 | } | ||||
| 1277 | } | ||||
| 1278 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1279 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1280 | } | ||||
| 1281 | |||||
| 1282 | void Verifier::visitDIFile(const DIFile &N) { | ||||
| 1283 | CheckDI(N.getTag() == dwarf::DW_TAG_file_type, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_file_type)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1284 | std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = N.getChecksum(); | ||||
| 1285 | if (Checksum) { | ||||
| 1286 | CheckDI(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last,do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false) | ||||
| 1287 | "invalid checksum kind", &N)do { if (!(Checksum->Kind <= DIFile::ChecksumKind::CSK_Last )) { DebugInfoCheckFailed("invalid checksum kind", &N); return ; } } while (false); | ||||
| 1288 | size_t Size; | ||||
| 1289 | switch (Checksum->Kind) { | ||||
| 1290 | case DIFile::CSK_MD5: | ||||
| 1291 | Size = 32; | ||||
| 1292 | break; | ||||
| 1293 | case DIFile::CSK_SHA1: | ||||
| 1294 | Size = 40; | ||||
| 1295 | break; | ||||
| 1296 | case DIFile::CSK_SHA256: | ||||
| 1297 | Size = 64; | ||||
| 1298 | break; | ||||
| 1299 | } | ||||
| 1300 | CheckDI(Checksum->Value.size() == Size, "invalid checksum length", &N)do { if (!(Checksum->Value.size() == Size)) { DebugInfoCheckFailed ("invalid checksum length", &N); return; } } while (false ); | ||||
| 1301 | CheckDI(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos,do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false) | ||||
| 1302 | "invalid checksum", &N)do { if (!(Checksum->Value.find_if_not(llvm::isHexDigit) == StringRef::npos)) { DebugInfoCheckFailed("invalid checksum", &N); return; } } while (false); | ||||
| 1303 | } | ||||
| 1304 | } | ||||
| 1305 | |||||
| 1306 | void Verifier::visitDICompileUnit(const DICompileUnit &N) { | ||||
| 1307 | CheckDI(N.isDistinct(), "compile units must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("compile units must be distinct" , &N); return; } } while (false); | ||||
| 1308 | CheckDI(N.getTag() == dwarf::DW_TAG_compile_unit, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_compile_unit)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1309 | |||||
| 1310 | // Don't bother verifying the compilation directory or producer string | ||||
| 1311 | // as those could be empty. | ||||
| 1312 | CheckDI(N.getRawFile() && isa<DIFile>(N.getRawFile()), "invalid file", &N,do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false) | ||||
| 1313 | N.getRawFile())do { if (!(N.getRawFile() && isa<DIFile>(N.getRawFile ()))) { DebugInfoCheckFailed("invalid file", &N, N.getRawFile ()); return; } } while (false); | ||||
| 1314 | CheckDI(!N.getFile()->getFilename().empty(), "invalid filename", &N,do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false) | ||||
| 1315 | N.getFile())do { if (!(!N.getFile()->getFilename().empty())) { DebugInfoCheckFailed ("invalid filename", &N, N.getFile()); return; } } while ( false); | ||||
| 1316 | |||||
| 1317 | CurrentSourceLang = (dwarf::SourceLanguage)N.getSourceLanguage(); | ||||
| 1318 | |||||
| 1319 | verifySourceDebugInfo(N, *N.getFile()); | ||||
| 1320 | |||||
| 1321 | CheckDI((N.getEmissionKind() <= DICompileUnit::LastEmissionKind),do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false) | ||||
| 1322 | "invalid emission kind", &N)do { if (!((N.getEmissionKind() <= DICompileUnit::LastEmissionKind ))) { DebugInfoCheckFailed("invalid emission kind", &N); return ; } } while (false); | ||||
| 1323 | |||||
| 1324 | if (auto *Array = N.getRawEnumTypes()) { | ||||
| 1325 | CheckDI(isa<MDTuple>(Array), "invalid enum list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid enum list", &N, Array); return; } } while (false ); | ||||
| 1326 | for (Metadata *Op : N.getEnumTypes()->operands()) { | ||||
| 1327 | auto *Enum = dyn_cast_or_null<DICompositeType>(Op); | ||||
| 1328 | CheckDI(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type,do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false) | ||||
| 1329 | "invalid enum type", &N, N.getEnumTypes(), Op)do { if (!(Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type )) { DebugInfoCheckFailed("invalid enum type", &N, N.getEnumTypes (), Op); return; } } while (false); | ||||
| 1330 | } | ||||
| 1331 | } | ||||
| 1332 | if (auto *Array = N.getRawRetainedTypes()) { | ||||
| 1333 | CheckDI(isa<MDTuple>(Array), "invalid retained type list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid retained type list", &N, Array); return; } } while (false); | ||||
| 1334 | for (Metadata *Op : N.getRetainedTypes()->operands()) { | ||||
| 1335 | CheckDI(do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1336 | Op && (isa<DIType>(Op) || (isa<DISubprogram>(Op) &&do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1337 | !cast<DISubprogram>(Op)->isDefinition())),do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false) | ||||
| 1338 | "invalid retained type", &N, Op)do { if (!(Op && (isa<DIType>(Op) || (isa<DISubprogram >(Op) && !cast<DISubprogram>(Op)->isDefinition ())))) { DebugInfoCheckFailed("invalid retained type", &N , Op); return; } } while (false); | ||||
| 1339 | } | ||||
| 1340 | } | ||||
| 1341 | if (auto *Array = N.getRawGlobalVariables()) { | ||||
| 1342 | CheckDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid global variable list", &N, Array); return; } } while (false); | ||||
| 1343 | for (Metadata *Op : N.getGlobalVariables()->operands()) { | ||||
| 1344 | CheckDI(Op && (isa<DIGlobalVariableExpression>(Op)),do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false) | ||||
| 1345 | "invalid global variable ref", &N, Op)do { if (!(Op && (isa<DIGlobalVariableExpression> (Op)))) { DebugInfoCheckFailed("invalid global variable ref", &N, Op); return; } } while (false); | ||||
| 1346 | } | ||||
| 1347 | } | ||||
| 1348 | if (auto *Array = N.getRawImportedEntities()) { | ||||
| 1349 | CheckDI(isa<MDTuple>(Array), "invalid imported entity list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid imported entity list", &N, Array); return; } } while (false); | ||||
| 1350 | for (Metadata *Op : N.getImportedEntities()->operands()) { | ||||
| 1351 | CheckDI(Op && isa<DIImportedEntity>(Op), "invalid imported entity ref",do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false) | ||||
| 1352 | &N, Op)do { if (!(Op && isa<DIImportedEntity>(Op))) { DebugInfoCheckFailed ("invalid imported entity ref", &N, Op); return; } } while (false); | ||||
| 1353 | } | ||||
| 1354 | } | ||||
| 1355 | if (auto *Array = N.getRawMacros()) { | ||||
| 1356 | CheckDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
| 1357 | for (Metadata *Op : N.getMacros()->operands()) { | ||||
| 1358 | CheckDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
| 1359 | } | ||||
| 1360 | } | ||||
| 1361 | CUVisited.insert(&N); | ||||
| 1362 | } | ||||
| 1363 | |||||
| 1364 | void Verifier::visitDISubprogram(const DISubprogram &N) { | ||||
| 1365 | CheckDI(N.getTag() == dwarf::DW_TAG_subprogram, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_subprogram)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1366 | CheckDI(isScope(N.getRawScope()), "invalid scope", &N, N.getRawScope())do { if (!(isScope(N.getRawScope()))) { DebugInfoCheckFailed( "invalid scope", &N, N.getRawScope()); return; } } while ( false); | ||||
| 1367 | if (auto *F = N.getRawFile()) | ||||
| 1368 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1369 | else | ||||
| 1370 | CheckDI(N.getLine() == 0, "line specified with no file", &N, N.getLine())do { if (!(N.getLine() == 0)) { DebugInfoCheckFailed("line specified with no file" , &N, N.getLine()); return; } } while (false); | ||||
| 1371 | if (auto *T = N.getRawType()) | ||||
| 1372 | CheckDI(isa<DISubroutineType>(T), "invalid subroutine type", &N, T)do { if (!(isa<DISubroutineType>(T))) { DebugInfoCheckFailed ("invalid subroutine type", &N, T); return; } } while (false ); | ||||
| 1373 | CheckDI(isType(N.getRawContainingType()), "invalid containing type", &N,do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false) | ||||
| 1374 | N.getRawContainingType())do { if (!(isType(N.getRawContainingType()))) { DebugInfoCheckFailed ("invalid containing type", &N, N.getRawContainingType()) ; return; } } while (false); | ||||
| 1375 | if (auto *Params = N.getRawTemplateParams()) | ||||
| 1376 | visitTemplateParams(N, *Params); | ||||
| 1377 | if (auto *S = N.getRawDeclaration()) | ||||
| 1378 | CheckDI(isa<DISubprogram>(S) && !cast<DISubprogram>(S)->isDefinition(),do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false) | ||||
| 1379 | "invalid subprogram declaration", &N, S)do { if (!(isa<DISubprogram>(S) && !cast<DISubprogram >(S)->isDefinition())) { DebugInfoCheckFailed("invalid subprogram declaration" , &N, S); return; } } while (false); | ||||
| 1380 | if (auto *RawNode = N.getRawRetainedNodes()) { | ||||
| 1381 | auto *Node = dyn_cast<MDTuple>(RawNode); | ||||
| 1382 | CheckDI(Node, "invalid retained nodes list", &N, RawNode)do { if (!(Node)) { DebugInfoCheckFailed("invalid retained nodes list" , &N, RawNode); return; } } while (false); | ||||
| 1383 | for (Metadata *Op : Node->operands()) { | ||||
| 1384 | CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op)),do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
| 1385 | "invalid retained nodes, expected DILocalVariable or DILabel", &N,do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false) | ||||
| 1386 | Node, Op)do { if (!(Op && (isa<DILocalVariable>(Op) || isa <DILabel>(Op)))) { DebugInfoCheckFailed("invalid retained nodes, expected DILocalVariable or DILabel" , &N, Node, Op); return; } } while (false); | ||||
| 1387 | } | ||||
| 1388 | } | ||||
| 1389 | CheckDI(!hasConflictingReferenceFlags(N.getFlags()),do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ) | ||||
| 1390 | "invalid reference flags", &N)do { if (!(!hasConflictingReferenceFlags(N.getFlags()))) { DebugInfoCheckFailed ("invalid reference flags", &N); return; } } while (false ); | ||||
| 1391 | |||||
| 1392 | auto *Unit = N.getRawUnit(); | ||||
| 1393 | if (N.isDefinition()) { | ||||
| 1394 | // Subprogram definitions (not part of the type hierarchy). | ||||
| 1395 | CheckDI(N.isDistinct(), "subprogram definitions must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("subprogram definitions must be distinct" , &N); return; } } while (false); | ||||
| 1396 | CheckDI(Unit, "subprogram definitions must have a compile unit", &N)do { if (!(Unit)) { DebugInfoCheckFailed("subprogram definitions must have a compile unit" , &N); return; } } while (false); | ||||
| 1397 | CheckDI(isa<DICompileUnit>(Unit), "invalid unit type", &N, Unit)do { if (!(isa<DICompileUnit>(Unit))) { DebugInfoCheckFailed ("invalid unit type", &N, Unit); return; } } while (false ); | ||||
| 1398 | if (N.getFile()) | ||||
| 1399 | verifySourceDebugInfo(*N.getUnit(), *N.getFile()); | ||||
| 1400 | } else { | ||||
| 1401 | // Subprogram declarations (part of the type hierarchy). | ||||
| 1402 | CheckDI(!Unit, "subprogram declarations must not have a compile unit", &N)do { if (!(!Unit)) { DebugInfoCheckFailed("subprogram declarations must not have a compile unit" , &N); return; } } while (false); | ||||
| 1403 | CheckDI(!N.getRawDeclaration(),do { if (!(!N.getRawDeclaration())) { DebugInfoCheckFailed("subprogram declaration must not have a declaration field" ); return; } } while (false) | ||||
| 1404 | "subprogram declaration must not have a declaration field")do { if (!(!N.getRawDeclaration())) { DebugInfoCheckFailed("subprogram declaration must not have a declaration field" ); return; } } while (false); | ||||
| 1405 | } | ||||
| 1406 | |||||
| 1407 | if (auto *RawThrownTypes = N.getRawThrownTypes()) { | ||||
| 1408 | auto *ThrownTypes = dyn_cast<MDTuple>(RawThrownTypes); | ||||
| 1409 | CheckDI(ThrownTypes, "invalid thrown types list", &N, RawThrownTypes)do { if (!(ThrownTypes)) { DebugInfoCheckFailed("invalid thrown types list" , &N, RawThrownTypes); return; } } while (false); | ||||
| 1410 | for (Metadata *Op : ThrownTypes->operands()) | ||||
| 1411 | CheckDI(Op && isa<DIType>(Op), "invalid thrown type", &N, ThrownTypes,do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false) | ||||
| 1412 | Op)do { if (!(Op && isa<DIType>(Op))) { DebugInfoCheckFailed ("invalid thrown type", &N, ThrownTypes, Op); return; } } while (false); | ||||
| 1413 | } | ||||
| 1414 | |||||
| 1415 | if (N.areAllCallsDescribed()) | ||||
| 1416 | CheckDI(N.isDefinition(),do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false) | ||||
| 1417 | "DIFlagAllCallsDescribed must be attached to a definition")do { if (!(N.isDefinition())) { DebugInfoCheckFailed("DIFlagAllCallsDescribed must be attached to a definition" ); return; } } while (false); | ||||
| 1418 | } | ||||
| 1419 | |||||
| 1420 | void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) { | ||||
| 1421 | CheckDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_lexical_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1422 | CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1423 | "invalid local scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("invalid local scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1424 | if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) | ||||
| 1425 | CheckDI(SP->isDefinition(), "scope points into the type hierarchy", &N)do { if (!(SP->isDefinition())) { DebugInfoCheckFailed("scope points into the type hierarchy" , &N); return; } } while (false); | ||||
| 1426 | } | ||||
| 1427 | |||||
| 1428 | void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { | ||||
| 1429 | visitDILexicalBlockBase(N); | ||||
| 1430 | |||||
| 1431 | CheckDI(N.getLine() || !N.getColumn(),do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false) | ||||
| 1432 | "cannot have column info without line info", &N)do { if (!(N.getLine() || !N.getColumn())) { DebugInfoCheckFailed ("cannot have column info without line info", &N); return ; } } while (false); | ||||
| 1433 | } | ||||
| 1434 | |||||
| 1435 | void Verifier::visitDILexicalBlockFile(const DILexicalBlockFile &N) { | ||||
| 1436 | visitDILexicalBlockBase(N); | ||||
| 1437 | } | ||||
| 1438 | |||||
| 1439 | void Verifier::visitDICommonBlock(const DICommonBlock &N) { | ||||
| 1440 | CheckDI(N.getTag() == dwarf::DW_TAG_common_block, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_common_block)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1441 | if (auto *S = N.getRawScope()) | ||||
| 1442 | CheckDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
| 1443 | if (auto *S = N.getRawDecl()) | ||||
| 1444 | CheckDI(isa<DIGlobalVariable>(S), "invalid declaration", &N, S)do { if (!(isa<DIGlobalVariable>(S))) { DebugInfoCheckFailed ("invalid declaration", &N, S); return; } } while (false); | ||||
| 1445 | } | ||||
| 1446 | |||||
| 1447 | void Verifier::visitDINamespace(const DINamespace &N) { | ||||
| 1448 | CheckDI(N.getTag() == dwarf::DW_TAG_namespace, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_namespace)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1449 | if (auto *S = N.getRawScope()) | ||||
| 1450 | CheckDI(isa<DIScope>(S), "invalid scope ref", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope ref" , &N, S); return; } } while (false); | ||||
| 1451 | } | ||||
| 1452 | |||||
| 1453 | void Verifier::visitDIMacro(const DIMacro &N) { | ||||
| 1454 | CheckDI(N.getMacinfoType() == dwarf::DW_MACINFO_define ||do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
| 1455 | N.getMacinfoType() == dwarf::DW_MACINFO_undef,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false) | ||||
| 1456 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_define || N .getMacinfoType() == dwarf::DW_MACINFO_undef)) { DebugInfoCheckFailed ("invalid macinfo type", &N); return; } } while (false); | ||||
| 1457 | CheckDI(!N.getName().empty(), "anonymous macro", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous macro" , &N); return; } } while (false); | ||||
| 1458 | if (!N.getValue().empty()) { | ||||
| 1459 | assert(N.getValue().data()[0] != ' ' && "Macro value has a space prefix")(static_cast <bool> (N.getValue().data()[0] != ' ' && "Macro value has a space prefix") ? void (0) : __assert_fail ("N.getValue().data()[0] != ' ' && \"Macro value has a space prefix\"" , "llvm/lib/IR/Verifier.cpp", 1459, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 1460 | } | ||||
| 1461 | } | ||||
| 1462 | |||||
| 1463 | void Verifier::visitDIMacroFile(const DIMacroFile &N) { | ||||
| 1464 | CheckDI(N.getMacinfoType() == dwarf::DW_MACINFO_start_file,do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false) | ||||
| 1465 | "invalid macinfo type", &N)do { if (!(N.getMacinfoType() == dwarf::DW_MACINFO_start_file )) { DebugInfoCheckFailed("invalid macinfo type", &N); return ; } } while (false); | ||||
| 1466 | if (auto *F = N.getRawFile()) | ||||
| 1467 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1468 | |||||
| 1469 | if (auto *Array = N.getRawElements()) { | ||||
| 1470 | CheckDI(isa<MDTuple>(Array), "invalid macro list", &N, Array)do { if (!(isa<MDTuple>(Array))) { DebugInfoCheckFailed ("invalid macro list", &N, Array); return; } } while (false ); | ||||
| 1471 | for (Metadata *Op : N.getElements()->operands()) { | ||||
| 1472 | CheckDI(Op && isa<DIMacroNode>(Op), "invalid macro ref", &N, Op)do { if (!(Op && isa<DIMacroNode>(Op))) { DebugInfoCheckFailed ("invalid macro ref", &N, Op); return; } } while (false); | ||||
| 1473 | } | ||||
| 1474 | } | ||||
| 1475 | } | ||||
| 1476 | |||||
| 1477 | void Verifier::visitDIArgList(const DIArgList &N) { | ||||
| 1478 | CheckDI(!N.getNumOperands(),do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1479 | "DIArgList should have no operands other than a list of "do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1480 | "ValueAsMetadata",do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false) | ||||
| 1481 | &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIArgList should have no operands other than a list of " "ValueAsMetadata", &N); return; } } while (false); | ||||
| 1482 | } | ||||
| 1483 | |||||
| 1484 | void Verifier::visitDIModule(const DIModule &N) { | ||||
| 1485 | CheckDI(N.getTag() == dwarf::DW_TAG_module, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_module)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1486 | CheckDI(!N.getName().empty(), "anonymous module", &N)do { if (!(!N.getName().empty())) { DebugInfoCheckFailed("anonymous module" , &N); return; } } while (false); | ||||
| 1487 | } | ||||
| 1488 | |||||
| 1489 | void Verifier::visitDITemplateParameter(const DITemplateParameter &N) { | ||||
| 1490 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1491 | } | ||||
| 1492 | |||||
| 1493 | void Verifier::visitDITemplateTypeParameter(const DITemplateTypeParameter &N) { | ||||
| 1494 | visitDITemplateParameter(N); | ||||
| 1495 | |||||
| 1496 | CheckDI(N.getTag() == dwarf::DW_TAG_template_type_parameter, "invalid tag",do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false) | ||||
| 1497 | &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_type_parameter )) { DebugInfoCheckFailed("invalid tag", &N); return; } } while (false); | ||||
| 1498 | } | ||||
| 1499 | |||||
| 1500 | void Verifier::visitDITemplateValueParameter( | ||||
| 1501 | const DITemplateValueParameter &N) { | ||||
| 1502 | visitDITemplateParameter(N); | ||||
| 1503 | |||||
| 1504 | CheckDI(N.getTag() == dwarf::DW_TAG_template_value_parameter ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1505 | N.getTag() == dwarf::DW_TAG_GNU_template_template_param ||do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1506 | N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack,do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1507 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_template_value_parameter || N.getTag() == dwarf::DW_TAG_GNU_template_template_param || N.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1508 | } | ||||
| 1509 | |||||
| 1510 | void Verifier::visitDIVariable(const DIVariable &N) { | ||||
| 1511 | if (auto *S = N.getRawScope()) | ||||
| 1512 | CheckDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
| 1513 | if (auto *F = N.getRawFile()) | ||||
| 1514 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1515 | } | ||||
| 1516 | |||||
| 1517 | void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) { | ||||
| 1518 | // Checks common to all variables. | ||||
| 1519 | visitDIVariable(N); | ||||
| 1520 | |||||
| 1521 | CheckDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1522 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1523 | // Check only if the global variable is not an extern | ||||
| 1524 | if (N.isDefinition()) | ||||
| 1525 | CheckDI(N.getType(), "missing global variable type", &N)do { if (!(N.getType())) { DebugInfoCheckFailed("missing global variable type" , &N); return; } } while (false); | ||||
| 1526 | if (auto *Member = N.getRawStaticDataMemberDeclaration()) { | ||||
| 1527 | CheckDI(isa<DIDerivedType>(Member),do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false) | ||||
| 1528 | "invalid static data member declaration", &N, Member)do { if (!(isa<DIDerivedType>(Member))) { DebugInfoCheckFailed ("invalid static data member declaration", &N, Member); return ; } } while (false); | ||||
| 1529 | } | ||||
| 1530 | } | ||||
| 1531 | |||||
| 1532 | void Verifier::visitDILocalVariable(const DILocalVariable &N) { | ||||
| 1533 | // Checks common to all variables. | ||||
| 1534 | visitDIVariable(N); | ||||
| 1535 | |||||
| 1536 | CheckDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType())do { if (!(isType(N.getRawType()))) { DebugInfoCheckFailed("invalid type ref" , &N, N.getRawType()); return; } } while (false); | ||||
| 1537 | CheckDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_variable)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1538 | CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1539 | "local variable requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("local variable requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1540 | if (auto Ty = N.getType()) | ||||
| 1541 | CheckDI(!isa<DISubroutineType>(Ty), "invalid type", &N, N.getType())do { if (!(!isa<DISubroutineType>(Ty))) { DebugInfoCheckFailed ("invalid type", &N, N.getType()); return; } } while (false ); | ||||
| 1542 | } | ||||
| 1543 | |||||
| 1544 | void Verifier::visitDIAssignID(const DIAssignID &N) { | ||||
| 1545 | CheckDI(!N.getNumOperands(), "DIAssignID has no arguments", &N)do { if (!(!N.getNumOperands())) { DebugInfoCheckFailed("DIAssignID has no arguments" , &N); return; } } while (false); | ||||
| 1546 | CheckDI(N.isDistinct(), "DIAssignID must be distinct", &N)do { if (!(N.isDistinct())) { DebugInfoCheckFailed("DIAssignID must be distinct" , &N); return; } } while (false); | ||||
| 1547 | } | ||||
| 1548 | |||||
| 1549 | void Verifier::visitDILabel(const DILabel &N) { | ||||
| 1550 | if (auto *S = N.getRawScope()) | ||||
| 1551 | CheckDI(isa<DIScope>(S), "invalid scope", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope" , &N, S); return; } } while (false); | ||||
| 1552 | if (auto *F = N.getRawFile()) | ||||
| 1553 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1554 | |||||
| 1555 | CheckDI(N.getTag() == dwarf::DW_TAG_label, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_label)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1556 | CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false) | ||||
| 1557 | "label requires a valid scope", &N, N.getRawScope())do { if (!(N.getRawScope() && isa<DILocalScope> (N.getRawScope()))) { DebugInfoCheckFailed("label requires a valid scope" , &N, N.getRawScope()); return; } } while (false); | ||||
| 1558 | } | ||||
| 1559 | |||||
| 1560 | void Verifier::visitDIExpression(const DIExpression &N) { | ||||
| 1561 | CheckDI(N.isValid(), "invalid expression", &N)do { if (!(N.isValid())) { DebugInfoCheckFailed("invalid expression" , &N); return; } } while (false); | ||||
| 1562 | } | ||||
| 1563 | |||||
| 1564 | void Verifier::visitDIGlobalVariableExpression( | ||||
| 1565 | const DIGlobalVariableExpression &GVE) { | ||||
| 1566 | CheckDI(GVE.getVariable(), "missing variable")do { if (!(GVE.getVariable())) { DebugInfoCheckFailed("missing variable" ); return; } } while (false); | ||||
| 1567 | if (auto *Var = GVE.getVariable()) | ||||
| 1568 | visitDIGlobalVariable(*Var); | ||||
| 1569 | if (auto *Expr = GVE.getExpression()) { | ||||
| 1570 | visitDIExpression(*Expr); | ||||
| 1571 | if (auto Fragment = Expr->getFragmentInfo()) | ||||
| 1572 | verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); | ||||
| 1573 | } | ||||
| 1574 | } | ||||
| 1575 | |||||
| 1576 | void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { | ||||
| 1577 | CheckDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_APPLE_property)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1578 | if (auto *T = N.getRawType()) | ||||
| 1579 | CheckDI(isType(T), "invalid type ref", &N, T)do { if (!(isType(T))) { DebugInfoCheckFailed("invalid type ref" , &N, T); return; } } while (false); | ||||
| 1580 | if (auto *F = N.getRawFile()) | ||||
| 1581 | CheckDI(isa<DIFile>(F), "invalid file", &N, F)do { if (!(isa<DIFile>(F))) { DebugInfoCheckFailed("invalid file" , &N, F); return; } } while (false); | ||||
| 1582 | } | ||||
| 1583 | |||||
| 1584 | void Verifier::visitDIImportedEntity(const DIImportedEntity &N) { | ||||
| 1585 | CheckDI(N.getTag() == dwarf::DW_TAG_imported_module ||do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1586 | N.getTag() == dwarf::DW_TAG_imported_declaration,do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false) | ||||
| 1587 | "invalid tag", &N)do { if (!(N.getTag() == dwarf::DW_TAG_imported_module || N.getTag () == dwarf::DW_TAG_imported_declaration)) { DebugInfoCheckFailed ("invalid tag", &N); return; } } while (false); | ||||
| 1588 | if (auto *S = N.getRawScope()) | ||||
| 1589 | CheckDI(isa<DIScope>(S), "invalid scope for imported entity", &N, S)do { if (!(isa<DIScope>(S))) { DebugInfoCheckFailed("invalid scope for imported entity" , &N, S); return; } } while (false); | ||||
| 1590 | CheckDI(isDINode(N.getRawEntity()), "invalid imported entity", &N,do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false) | ||||
| 1591 | N.getRawEntity())do { if (!(isDINode(N.getRawEntity()))) { DebugInfoCheckFailed ("invalid imported entity", &N, N.getRawEntity()); return ; } } while (false); | ||||
| 1592 | } | ||||
| 1593 | |||||
| 1594 | void Verifier::visitComdat(const Comdat &C) { | ||||
| 1595 | // In COFF the Module is invalid if the GlobalValue has private linkage. | ||||
| 1596 | // Entities with private linkage don't have entries in the symbol table. | ||||
| 1597 | if (TT.isOSBinFormatCOFF()) | ||||
| 1598 | if (const GlobalValue *GV = M.getNamedValue(C.getName())) | ||||
| 1599 | Check(!GV->hasPrivateLinkage(), "comdat global value has private linkage",do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false) | ||||
| 1600 | GV)do { if (!(!GV->hasPrivateLinkage())) { CheckFailed("comdat global value has private linkage" , GV); return; } } while (false); | ||||
| 1601 | } | ||||
| 1602 | |||||
| 1603 | void Verifier::visitModuleIdents() { | ||||
| 1604 | const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident"); | ||||
| 1605 | if (!Idents) | ||||
| 1606 | return; | ||||
| 1607 | |||||
| 1608 | // llvm.ident takes a list of metadata entry. Each entry has only one string. | ||||
| 1609 | // Scan each llvm.ident entry and make sure that this requirement is met. | ||||
| 1610 | for (const MDNode *N : Idents->operands()) { | ||||
| 1611 | Check(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false) | ||||
| 1612 | "incorrect number of operands in llvm.ident metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.ident metadata" , N); return; } } while (false); | ||||
| 1613 | Check(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1614 | ("invalid value for llvm.ident metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1615 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1616 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.ident metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
| 1617 | } | ||||
| 1618 | } | ||||
| 1619 | |||||
| 1620 | void Verifier::visitModuleCommandLines() { | ||||
| 1621 | const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); | ||||
| 1622 | if (!CommandLines) | ||||
| 1623 | return; | ||||
| 1624 | |||||
| 1625 | // llvm.commandline takes a list of metadata entry. Each entry has only one | ||||
| 1626 | // string. Scan each llvm.commandline entry and make sure that this | ||||
| 1627 | // requirement is met. | ||||
| 1628 | for (const MDNode *N : CommandLines->operands()) { | ||||
| 1629 | Check(N->getNumOperands() == 1,do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false) | ||||
| 1630 | "incorrect number of operands in llvm.commandline metadata", N)do { if (!(N->getNumOperands() == 1)) { CheckFailed("incorrect number of operands in llvm.commandline metadata" , N); return; } } while (false); | ||||
| 1631 | Check(dyn_cast_or_null<MDString>(N->getOperand(0)),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1632 | ("invalid value for llvm.commandline metadata entry operand"do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1633 | "(the operand should be a string)"),do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false) | ||||
| 1634 | N->getOperand(0))do { if (!(dyn_cast_or_null<MDString>(N->getOperand( 0)))) { CheckFailed(("invalid value for llvm.commandline metadata entry operand" "(the operand should be a string)"), N->getOperand(0)); return ; } } while (false); | ||||
| 1635 | } | ||||
| 1636 | } | ||||
| 1637 | |||||
| 1638 | void Verifier::visitModuleFlags() { | ||||
| 1639 | const NamedMDNode *Flags = M.getModuleFlagsMetadata(); | ||||
| 1640 | if (!Flags) return; | ||||
| 1641 | |||||
| 1642 | // Scan each flag, and track the flags and requirements. | ||||
| 1643 | DenseMap<const MDString*, const MDNode*> SeenIDs; | ||||
| 1644 | SmallVector<const MDNode*, 16> Requirements; | ||||
| 1645 | for (const MDNode *MDN : Flags->operands()) | ||||
| 1646 | visitModuleFlag(MDN, SeenIDs, Requirements); | ||||
| 1647 | |||||
| 1648 | // Validate that the requirements in the module are valid. | ||||
| 1649 | for (const MDNode *Requirement : Requirements) { | ||||
| 1650 | const MDString *Flag = cast<MDString>(Requirement->getOperand(0)); | ||||
| 1651 | const Metadata *ReqValue = Requirement->getOperand(1); | ||||
| 1652 | |||||
| 1653 | const MDNode *Op = SeenIDs.lookup(Flag); | ||||
| 1654 | if (!Op) { | ||||
| 1655 | CheckFailed("invalid requirement on flag, flag is not present in module", | ||||
| 1656 | Flag); | ||||
| 1657 | continue; | ||||
| 1658 | } | ||||
| 1659 | |||||
| 1660 | if (Op->getOperand(2) != ReqValue) { | ||||
| 1661 | CheckFailed(("invalid requirement on flag, " | ||||
| 1662 | "flag does not have the required value"), | ||||
| 1663 | Flag); | ||||
| 1664 | continue; | ||||
| 1665 | } | ||||
| 1666 | } | ||||
| 1667 | } | ||||
| 1668 | |||||
| 1669 | void | ||||
| 1670 | Verifier::visitModuleFlag(const MDNode *Op, | ||||
| 1671 | DenseMap<const MDString *, const MDNode *> &SeenIDs, | ||||
| 1672 | SmallVectorImpl<const MDNode *> &Requirements) { | ||||
| 1673 | // Each module flag should have three arguments, the merge behavior (a | ||||
| 1674 | // constant int), the flag ID (an MDString), and the value. | ||||
| 1675 | Check(Op->getNumOperands() == 3,do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false) | ||||
| 1676 | "incorrect number of operands in module flag", Op)do { if (!(Op->getNumOperands() == 3)) { CheckFailed("incorrect number of operands in module flag" , Op); return; } } while (false); | ||||
| 1677 | Module::ModFlagBehavior MFB; | ||||
| 1678 | if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { | ||||
| 1679 | Check(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(0)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1680 | "invalid behavior operand in module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1681 | Op->getOperand(0))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(0)))) { CheckFailed("invalid behavior operand in module flag (expected constant integer)" , Op->getOperand(0)); return; } } while (false); | ||||
| 1682 | Check(false,do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1683 | "invalid behavior operand in module flag (unexpected constant)",do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false) | ||||
| 1684 | Op->getOperand(0))do { if (!(false)) { CheckFailed("invalid behavior operand in module flag (unexpected constant)" , Op->getOperand(0)); return; } } while (false); | ||||
| 1685 | } | ||||
| 1686 | MDString *ID = dyn_cast_or_null<MDString>(Op->getOperand(1)); | ||||
| 1687 | Check(ID, "invalid ID operand in module flag (expected metadata string)",do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false) | ||||
| 1688 | Op->getOperand(1))do { if (!(ID)) { CheckFailed("invalid ID operand in module flag (expected metadata string)" , Op->getOperand(1)); return; } } while (false); | ||||
| 1689 | |||||
| 1690 | // Check the values for behaviors with additional requirements. | ||||
| 1691 | switch (MFB) { | ||||
| 1692 | case Module::Error: | ||||
| 1693 | case Module::Warning: | ||||
| 1694 | case Module::Override: | ||||
| 1695 | // These behavior types accept any value. | ||||
| 1696 | break; | ||||
| 1697 | |||||
| 1698 | case Module::Min: { | ||||
| 1699 | auto *V = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
| 1700 | Check(V && V->getValue().isNonNegative(),do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
| 1701 | "invalid value for 'min' module flag (expected constant non-negative "do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
| 1702 | "integer)",do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false) | ||||
| 1703 | Op->getOperand(2))do { if (!(V && V->getValue().isNonNegative())) { CheckFailed ("invalid value for 'min' module flag (expected constant non-negative " "integer)", Op->getOperand(2)); return; } } while (false); | ||||
| 1704 | break; | ||||
| 1705 | } | ||||
| 1706 | |||||
| 1707 | case Module::Max: { | ||||
| 1708 | Check(mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1709 | "invalid value for 'max' module flag (expected constant integer)",do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1710 | Op->getOperand(2))do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ->getOperand(2)))) { CheckFailed("invalid value for 'max' module flag (expected constant integer)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1711 | break; | ||||
| 1712 | } | ||||
| 1713 | |||||
| 1714 | case Module::Require: { | ||||
| 1715 | // The value should itself be an MDNode with two operands, a flag ID (an | ||||
| 1716 | // MDString), and a value. | ||||
| 1717 | MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2)); | ||||
| 1718 | Check(Value && Value->getNumOperands() == 2,do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1719 | "invalid value for 'require' module flag (expected metadata pair)",do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1720 | Op->getOperand(2))do { if (!(Value && Value->getNumOperands() == 2)) { CheckFailed("invalid value for 'require' module flag (expected metadata pair)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1721 | Check(isa<MDString>(Value->getOperand(0)),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1722 | ("invalid value for 'require' module flag "do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1723 | "(first value operand should be a string)"),do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false) | ||||
| 1724 | Value->getOperand(0))do { if (!(isa<MDString>(Value->getOperand(0)))) { CheckFailed (("invalid value for 'require' module flag " "(first value operand should be a string)" ), Value->getOperand(0)); return; } } while (false); | ||||
| 1725 | |||||
| 1726 | // Append it to the list of requirements, to check once all module flags are | ||||
| 1727 | // scanned. | ||||
| 1728 | Requirements.push_back(Value); | ||||
| 1729 | break; | ||||
| 1730 | } | ||||
| 1731 | |||||
| 1732 | case Module::Append: | ||||
| 1733 | case Module::AppendUnique: { | ||||
| 1734 | // These behavior types require the operand be an MDNode. | ||||
| 1735 | Check(isa<MDNode>(Op->getOperand(2)),do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1736 | "invalid value for 'append'-type module flag "do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1737 | "(expected a metadata node)",do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false) | ||||
| 1738 | Op->getOperand(2))do { if (!(isa<MDNode>(Op->getOperand(2)))) { CheckFailed ("invalid value for 'append'-type module flag " "(expected a metadata node)" , Op->getOperand(2)); return; } } while (false); | ||||
| 1739 | break; | ||||
| 1740 | } | ||||
| 1741 | } | ||||
| 1742 | |||||
| 1743 | // Unless this is a "requires" flag, check the ID is unique. | ||||
| 1744 | if (MFB != Module::Require) { | ||||
| 1745 | bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; | ||||
| 1746 | Check(Inserted,do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false) | ||||
| 1747 | "module flag identifiers must be unique (or of 'require' type)", ID)do { if (!(Inserted)) { CheckFailed("module flag identifiers must be unique (or of 'require' type)" , ID); return; } } while (false); | ||||
| 1748 | } | ||||
| 1749 | |||||
| 1750 | if (ID->getString() == "wchar_size") { | ||||
| 1751 | ConstantInt *Value | ||||
| 1752 | = mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
| 1753 | Check(Value, "wchar_size metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("wchar_size metadata requires constant integer argument" ); return; } } while (false); | ||||
| 1754 | } | ||||
| 1755 | |||||
| 1756 | if (ID->getString() == "Linker Options") { | ||||
| 1757 | // If the llvm.linker.options named metadata exists, we assume that the | ||||
| 1758 | // bitcode reader has upgraded the module flag. Otherwise the flag might | ||||
| 1759 | // have been created by a client directly. | ||||
| 1760 | Check(M.getNamedMetadata("llvm.linker.options"),do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false) | ||||
| 1761 | "'Linker Options' named metadata no longer supported")do { if (!(M.getNamedMetadata("llvm.linker.options"))) { CheckFailed ("'Linker Options' named metadata no longer supported"); return ; } } while (false); | ||||
| 1762 | } | ||||
| 1763 | |||||
| 1764 | if (ID->getString() == "SemanticInterposition") { | ||||
| 1765 | ConstantInt *Value = | ||||
| 1766 | mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2)); | ||||
| 1767 | Check(Value,do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false) | ||||
| 1768 | "SemanticInterposition metadata requires constant integer argument")do { if (!(Value)) { CheckFailed("SemanticInterposition metadata requires constant integer argument" ); return; } } while (false); | ||||
| 1769 | } | ||||
| 1770 | |||||
| 1771 | if (ID->getString() == "CG Profile") { | ||||
| 1772 | for (const MDOperand &MDO : cast<MDNode>(Op->getOperand(2))->operands()) | ||||
| 1773 | visitModuleFlagCGProfileEntry(MDO); | ||||
| 1774 | } | ||||
| 1775 | } | ||||
| 1776 | |||||
| 1777 | void Verifier::visitModuleFlagCGProfileEntry(const MDOperand &MDO) { | ||||
| 1778 | auto CheckFunction = [&](const MDOperand &FuncMDO) { | ||||
| 1779 | if (!FuncMDO) | ||||
| 1780 | return; | ||||
| 1781 | auto F = dyn_cast<ValueAsMetadata>(FuncMDO); | ||||
| 1782 | Check(F && isa<Function>(F->getValue()->stripPointerCasts()),do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false) | ||||
| 1783 | "expected a Function or null", FuncMDO)do { if (!(F && isa<Function>(F->getValue()-> stripPointerCasts()))) { CheckFailed("expected a Function or null" , FuncMDO); return; } } while (false); | ||||
| 1784 | }; | ||||
| 1785 | auto Node = dyn_cast_or_null<MDNode>(MDO); | ||||
| 1786 | Check(Node && Node->getNumOperands() == 3, "expected a MDNode triple", MDO)do { if (!(Node && Node->getNumOperands() == 3)) { CheckFailed("expected a MDNode triple", MDO); return; } } while (false); | ||||
| 1787 | CheckFunction(Node->getOperand(0)); | ||||
| 1788 | CheckFunction(Node->getOperand(1)); | ||||
| 1789 | auto Count = dyn_cast_or_null<ConstantAsMetadata>(Node->getOperand(2)); | ||||
| 1790 | Check(Count && Count->getType()->isIntegerTy(),do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false) | ||||
| 1791 | "expected an integer constant", Node->getOperand(2))do { if (!(Count && Count->getType()->isIntegerTy ())) { CheckFailed("expected an integer constant", Node->getOperand (2)); return; } } while (false); | ||||
| 1792 | } | ||||
| 1793 | |||||
| 1794 | void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) { | ||||
| 1795 | for (Attribute A : Attrs) { | ||||
| 1796 | |||||
| 1797 | if (A.isStringAttribute()) { | ||||
| 1798 | #define GET_ATTR_NAMES | ||||
| 1799 | #define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) | ||||
| 1800 | #define ATTRIBUTE_STRBOOL(ENUM_NAME, DISPLAY_NAME) \ | ||||
| 1801 | if (A.getKindAsString() == #DISPLAY_NAME) { \ | ||||
| 1802 | auto V = A.getValueAsString(); \ | ||||
| 1803 | if (!(V.empty() || V == "true" || V == "false")) \ | ||||
| 1804 | CheckFailed("invalid value for '" #DISPLAY_NAME "' attribute: " + V + \ | ||||
| 1805 | ""); \ | ||||
| 1806 | } | ||||
| 1807 | |||||
| 1808 | #include "llvm/IR/Attributes.inc" | ||||
| 1809 | continue; | ||||
| 1810 | } | ||||
| 1811 | |||||
| 1812 | if (A.isIntAttribute() != Attribute::isIntAttrKind(A.getKindAsEnum())) { | ||||
| 1813 | CheckFailed("Attribute '" + A.getAsString() + "' should have an Argument", | ||||
| 1814 | V); | ||||
| 1815 | return; | ||||
| 1816 | } | ||||
| 1817 | } | ||||
| 1818 | } | ||||
| 1819 | |||||
| 1820 | // VerifyParameterAttrs - Check the given attributes for an argument or return | ||||
| 1821 | // value of the specified type. The value V is printed in error messages. | ||||
| 1822 | void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty, | ||||
| 1823 | const Value *V) { | ||||
| 1824 | if (!Attrs.hasAttributes()) | ||||
| 1825 | return; | ||||
| 1826 | |||||
| 1827 | verifyAttributeTypes(Attrs, V); | ||||
| 1828 | |||||
| 1829 | for (Attribute Attr : Attrs) | ||||
| 1830 | Check(Attr.isStringAttribute() ||do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1831 | Attribute::canUseAsParamAttr(Attr.getKindAsEnum()),do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1832 | "Attribute '" + Attr.getAsString() + "' does not apply to parameters",do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false) | ||||
| 1833 | V)do { if (!(Attr.isStringAttribute() || Attribute::canUseAsParamAttr (Attr.getKindAsEnum()))) { CheckFailed("Attribute '" + Attr.getAsString () + "' does not apply to parameters", V); return; } } while ( false); | ||||
| 1834 | |||||
| 1835 | if (Attrs.hasAttribute(Attribute::ImmArg)) { | ||||
| 1836 | Check(Attrs.getNumAttributes() == 1,do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false) | ||||
| 1837 | "Attribute 'immarg' is incompatible with other attributes", V)do { if (!(Attrs.getNumAttributes() == 1)) { CheckFailed("Attribute 'immarg' is incompatible with other attributes" , V); return; } } while (false); | ||||
| 1838 | } | ||||
| 1839 | |||||
| 1840 | // Check for mutually incompatible attributes. Only inreg is compatible with | ||||
| 1841 | // sret. | ||||
| 1842 | unsigned AttrCount = 0; | ||||
| 1843 | AttrCount += Attrs.hasAttribute(Attribute::ByVal); | ||||
| 1844 | AttrCount += Attrs.hasAttribute(Attribute::InAlloca); | ||||
| 1845 | AttrCount += Attrs.hasAttribute(Attribute::Preallocated); | ||||
| 1846 | AttrCount += Attrs.hasAttribute(Attribute::StructRet) || | ||||
| 1847 | Attrs.hasAttribute(Attribute::InReg); | ||||
| 1848 | AttrCount += Attrs.hasAttribute(Attribute::Nest); | ||||
| 1849 | AttrCount += Attrs.hasAttribute(Attribute::ByRef); | ||||
| 1850 | Check(AttrCount <= 1,do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1851 | "Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', "do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1852 | "'byref', and 'sret' are incompatible!",do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false) | ||||
| 1853 | V)do { if (!(AttrCount <= 1)) { CheckFailed("Attributes 'byval', 'inalloca', 'preallocated', 'inreg', 'nest', " "'byref', and 'sret' are incompatible!", V); return; } } while (false); | ||||
| 1854 | |||||
| 1855 | Check(!(Attrs.hasAttribute(Attribute::InAlloca) &&do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1856 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1857 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1858 | "'inalloca and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1859 | V)do { if (!(!(Attrs.hasAttribute(Attribute::InAlloca) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'inalloca and readonly' are incompatible!", V); return; } } while (false); | ||||
| 1860 | |||||
| 1861 | Check(!(Attrs.hasAttribute(Attribute::StructRet) &&do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1862 | Attrs.hasAttribute(Attribute::Returned)),do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1863 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1864 | "'sret and returned' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false) | ||||
| 1865 | V)do { if (!(!(Attrs.hasAttribute(Attribute::StructRet) && Attrs.hasAttribute(Attribute::Returned)))) { CheckFailed("Attributes " "'sret and returned' are incompatible!", V); return; } } while (false); | ||||
| 1866 | |||||
| 1867 | Check(!(Attrs.hasAttribute(Attribute::ZExt) &&do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1868 | Attrs.hasAttribute(Attribute::SExt)),do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1869 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1870 | "'zeroext and signext' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false) | ||||
| 1871 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ZExt) && Attrs .hasAttribute(Attribute::SExt)))) { CheckFailed("Attributes " "'zeroext and signext' are incompatible!", V); return; } } while (false); | ||||
| 1872 | |||||
| 1873 | Check(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1874 | Attrs.hasAttribute(Attribute::ReadOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1875 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1876 | "'readnone and readonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false) | ||||
| 1877 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::ReadOnly)))) { CheckFailed("Attributes " "'readnone and readonly' are incompatible!", V); return; } } while (false); | ||||
| 1878 | |||||
| 1879 | Check(!(Attrs.hasAttribute(Attribute::ReadNone) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1880 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1881 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1882 | "'readnone and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1883 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadNone) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readnone and writeonly' are incompatible!", V); return; } } while (false); | ||||
| 1884 | |||||
| 1885 | Check(!(Attrs.hasAttribute(Attribute::ReadOnly) &&do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1886 | Attrs.hasAttribute(Attribute::WriteOnly)),do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1887 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1888 | "'readonly and writeonly' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false) | ||||
| 1889 | V)do { if (!(!(Attrs.hasAttribute(Attribute::ReadOnly) && Attrs.hasAttribute(Attribute::WriteOnly)))) { CheckFailed("Attributes " "'readonly and writeonly' are incompatible!", V); return; } } while (false); | ||||
| 1890 | |||||
| 1891 | Check(!(Attrs.hasAttribute(Attribute::NoInline) &&do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1892 | Attrs.hasAttribute(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1893 | "Attributes "do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1894 | "'noinline and alwaysinline' are incompatible!",do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 1895 | V)do { if (!(!(Attrs.hasAttribute(Attribute::NoInline) && Attrs.hasAttribute(Attribute::AlwaysInline)))) { CheckFailed ("Attributes " "'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
| 1896 | |||||
| 1897 | AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible(Ty); | ||||
| 1898 | for (Attribute Attr : Attrs) { | ||||
| 1899 | if (!Attr.isStringAttribute() && | ||||
| 1900 | IncompatibleAttrs.contains(Attr.getKindAsEnum())) { | ||||
| 1901 | CheckFailed("Attribute '" + Attr.getAsString() + | ||||
| 1902 | "' applied to incompatible type!", V); | ||||
| 1903 | return; | ||||
| 1904 | } | ||||
| 1905 | } | ||||
| 1906 | |||||
| 1907 | if (PointerType *PTy = dyn_cast<PointerType>(Ty)) { | ||||
| 1908 | if (Attrs.hasAttribute(Attribute::ByVal)) { | ||||
| 1909 | if (Attrs.hasAttribute(Attribute::Alignment)) { | ||||
| 1910 | Align AttrAlign = Attrs.getAlignment().valueOrOne(); | ||||
| 1911 | Align MaxAlign(ParamMaxAlignment); | ||||
| 1912 | Check(AttrAlign <= MaxAlign,do { if (!(AttrAlign <= MaxAlign)) { CheckFailed("Attribute 'align' exceed the max size 2^14" , V); return; } } while (false) | ||||
| 1913 | "Attribute 'align' exceed the max size 2^14", V)do { if (!(AttrAlign <= MaxAlign)) { CheckFailed("Attribute 'align' exceed the max size 2^14" , V); return; } } while (false); | ||||
| 1914 | } | ||||
| 1915 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1916 | Check(Attrs.getByValType()->isSized(&Visited),do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false) | ||||
| 1917 | "Attribute 'byval' does not support unsized types!", V)do { if (!(Attrs.getByValType()->isSized(&Visited))) { CheckFailed("Attribute 'byval' does not support unsized types!" , V); return; } } while (false); | ||||
| 1918 | } | ||||
| 1919 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
| 1920 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1921 | Check(Attrs.getByRefType()->isSized(&Visited),do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false) | ||||
| 1922 | "Attribute 'byref' does not support unsized types!", V)do { if (!(Attrs.getByRefType()->isSized(&Visited))) { CheckFailed("Attribute 'byref' does not support unsized types!" , V); return; } } while (false); | ||||
| 1923 | } | ||||
| 1924 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 1925 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1926 | Check(Attrs.getInAllocaType()->isSized(&Visited),do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false) | ||||
| 1927 | "Attribute 'inalloca' does not support unsized types!", V)do { if (!(Attrs.getInAllocaType()->isSized(&Visited)) ) { CheckFailed("Attribute 'inalloca' does not support unsized types!" , V); return; } } while (false); | ||||
| 1928 | } | ||||
| 1929 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
| 1930 | SmallPtrSet<Type *, 4> Visited; | ||||
| 1931 | Check(Attrs.getPreallocatedType()->isSized(&Visited),do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false) | ||||
| 1932 | "Attribute 'preallocated' does not support unsized types!", V)do { if (!(Attrs.getPreallocatedType()->isSized(&Visited ))) { CheckFailed("Attribute 'preallocated' does not support unsized types!" , V); return; } } while (false); | ||||
| 1933 | } | ||||
| 1934 | if (!PTy->isOpaque()) { | ||||
| 1935 | if (!isa<PointerType>(PTy->getNonOpaquePointerElementType())) | ||||
| 1936 | Check(!Attrs.hasAttribute(Attribute::SwiftError),do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1937 | "Attribute 'swifterror' only applies to parameters "do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1938 | "with pointer to pointer type!",do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false) | ||||
| 1939 | V)do { if (!(!Attrs.hasAttribute(Attribute::SwiftError))) { CheckFailed ("Attribute 'swifterror' only applies to parameters " "with pointer to pointer type!" , V); return; } } while (false); | ||||
| 1940 | if (Attrs.hasAttribute(Attribute::ByRef)) { | ||||
| 1941 | Check(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false) | ||||
| 1942 | "Attribute 'byref' type does not match parameter!", V)do { if (!(Attrs.getByRefType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byref' type does not match parameter!" , V); return; } } while (false); | ||||
| 1943 | } | ||||
| 1944 | |||||
| 1945 | if (Attrs.hasAttribute(Attribute::ByVal) && Attrs.getByValType()) { | ||||
| 1946 | Check(Attrs.getByValType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getByValType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false) | ||||
| 1947 | "Attribute 'byval' type does not match parameter!", V)do { if (!(Attrs.getByValType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'byval' type does not match parameter!" , V); return; } } while (false); | ||||
| 1948 | } | ||||
| 1949 | |||||
| 1950 | if (Attrs.hasAttribute(Attribute::Preallocated)) { | ||||
| 1951 | Check(Attrs.getPreallocatedType() ==do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
| 1952 | PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false) | ||||
| 1953 | "Attribute 'preallocated' type does not match parameter!", V)do { if (!(Attrs.getPreallocatedType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'preallocated' type does not match parameter!" , V); return; } } while (false); | ||||
| 1954 | } | ||||
| 1955 | |||||
| 1956 | if (Attrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 1957 | Check(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false) | ||||
| 1958 | "Attribute 'inalloca' type does not match parameter!", V)do { if (!(Attrs.getInAllocaType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'inalloca' type does not match parameter!" , V); return; } } while (false); | ||||
| 1959 | } | ||||
| 1960 | |||||
| 1961 | if (Attrs.hasAttribute(Attribute::ElementType)) { | ||||
| 1962 | Check(Attrs.getElementType() == PTy->getNonOpaquePointerElementType(),do { if (!(Attrs.getElementType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false) | ||||
| 1963 | "Attribute 'elementtype' type does not match parameter!", V)do { if (!(Attrs.getElementType() == PTy->getNonOpaquePointerElementType ())) { CheckFailed("Attribute 'elementtype' type does not match parameter!" , V); return; } } while (false); | ||||
| 1964 | } | ||||
| 1965 | } | ||||
| 1966 | } | ||||
| 1967 | |||||
| 1968 | if (Attrs.hasAttribute(Attribute::NoFPClass)) { | ||||
| 1969 | uint64_t Val = Attrs.getAttribute(Attribute::NoFPClass).getValueAsInt(); | ||||
| 1970 | Check(Val != 0, "Attribute 'nofpclass' must have at least one test bit set",do { if (!(Val != 0)) { CheckFailed("Attribute 'nofpclass' must have at least one test bit set" , V); return; } } while (false) | ||||
| 1971 | V)do { if (!(Val != 0)) { CheckFailed("Attribute 'nofpclass' must have at least one test bit set" , V); return; } } while (false); | ||||
| 1972 | Check((Val & ~static_cast<unsigned>(fcAllFlags)) == 0,do { if (!((Val & ~static_cast<unsigned>(fcAllFlags )) == 0)) { CheckFailed("Invalid value for 'nofpclass' test mask" , V); return; } } while (false) | ||||
| 1973 | "Invalid value for 'nofpclass' test mask", V)do { if (!((Val & ~static_cast<unsigned>(fcAllFlags )) == 0)) { CheckFailed("Invalid value for 'nofpclass' test mask" , V); return; } } while (false); | ||||
| 1974 | } | ||||
| 1975 | } | ||||
| 1976 | |||||
| 1977 | void Verifier::checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr, | ||||
| 1978 | const Value *V) { | ||||
| 1979 | if (Attrs.hasFnAttr(Attr)) { | ||||
| 1980 | StringRef S = Attrs.getFnAttr(Attr).getValueAsString(); | ||||
| 1981 | unsigned N; | ||||
| 1982 | if (S.getAsInteger(10, N)) | ||||
| 1983 | CheckFailed("\"" + Attr + "\" takes an unsigned integer: " + S, V); | ||||
| 1984 | } | ||||
| 1985 | } | ||||
| 1986 | |||||
| 1987 | // Check parameter attributes against a function type. | ||||
| 1988 | // The value V is printed in error messages. | ||||
| 1989 | void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs, | ||||
| 1990 | const Value *V, bool IsIntrinsic, | ||||
| 1991 | bool IsInlineAsm) { | ||||
| 1992 | if (Attrs.isEmpty()) | ||||
| 1993 | return; | ||||
| 1994 | |||||
| 1995 | if (AttributeListsVisited.insert(Attrs.getRawPointer()).second) { | ||||
| 1996 | Check(Attrs.hasParentContext(Context),do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false) | ||||
| 1997 | "Attribute list does not match Module context!", &Attrs, V)do { if (!(Attrs.hasParentContext(Context))) { CheckFailed("Attribute list does not match Module context!" , &Attrs, V); return; } } while (false); | ||||
| 1998 | for (const auto &AttrSet : Attrs) { | ||||
| 1999 | Check(!AttrSet.hasAttributes() || AttrSet.hasParentContext(Context),do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false) | ||||
| 2000 | "Attribute set does not match Module context!", &AttrSet, V)do { if (!(!AttrSet.hasAttributes() || AttrSet.hasParentContext (Context))) { CheckFailed("Attribute set does not match Module context!" , &AttrSet, V); return; } } while (false); | ||||
| 2001 | for (const auto &A : AttrSet) { | ||||
| 2002 | Check(A.hasParentContext(Context),do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false) | ||||
| 2003 | "Attribute does not match Module context!", &A, V)do { if (!(A.hasParentContext(Context))) { CheckFailed("Attribute does not match Module context!" , &A, V); return; } } while (false); | ||||
| 2004 | } | ||||
| 2005 | } | ||||
| 2006 | } | ||||
| 2007 | |||||
| 2008 | bool SawNest = false; | ||||
| 2009 | bool SawReturned = false; | ||||
| 2010 | bool SawSRet = false; | ||||
| 2011 | bool SawSwiftSelf = false; | ||||
| 2012 | bool SawSwiftAsync = false; | ||||
| 2013 | bool SawSwiftError = false; | ||||
| 2014 | |||||
| 2015 | // Verify return value attributes. | ||||
| 2016 | AttributeSet RetAttrs = Attrs.getRetAttrs(); | ||||
| 2017 | for (Attribute RetAttr : RetAttrs) | ||||
| 2018 | Check(RetAttr.isStringAttribute() ||do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 2019 | Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()),do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 2020 | "Attribute '" + RetAttr.getAsString() +do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 2021 | "' does not apply to function return values",do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false) | ||||
| 2022 | V)do { if (!(RetAttr.isStringAttribute() || Attribute::canUseAsRetAttr (RetAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + RetAttr .getAsString() + "' does not apply to function return values" , V); return; } } while (false); | ||||
| 2023 | |||||
| 2024 | verifyParameterAttrs(RetAttrs, FT->getReturnType(), V); | ||||
| 2025 | |||||
| 2026 | // Verify parameter attributes. | ||||
| 2027 | for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { | ||||
| 2028 | Type *Ty = FT->getParamType(i); | ||||
| 2029 | AttributeSet ArgAttrs = Attrs.getParamAttrs(i); | ||||
| 2030 | |||||
| 2031 | if (!IsIntrinsic) { | ||||
| 2032 | Check(!ArgAttrs.hasAttribute(Attribute::ImmArg),do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics", V); return; } } while (false) | ||||
| 2033 | "immarg attribute only applies to intrinsics", V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ImmArg))) { CheckFailed ("immarg attribute only applies to intrinsics", V); return; } } while (false); | ||||
| 2034 | if (!IsInlineAsm) | ||||
| 2035 | Check(!ArgAttrs.hasAttribute(Attribute::ElementType),do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
| 2036 | "Attribute 'elementtype' can only be applied to intrinsics"do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
| 2037 | " and inline asm.",do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false) | ||||
| 2038 | V)do { if (!(!ArgAttrs.hasAttribute(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to intrinsics" " and inline asm.", V); return; } } while (false); | ||||
| 2039 | } | ||||
| 2040 | |||||
| 2041 | verifyParameterAttrs(ArgAttrs, Ty, V); | ||||
| 2042 | |||||
| 2043 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
| 2044 | Check(!SawNest, "More than one parameter has attribute nest!", V)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , V); return; } } while (false); | ||||
| 2045 | SawNest = true; | ||||
| 2046 | } | ||||
| 2047 | |||||
| 2048 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
| 2049 | Check(!SawReturned, "More than one parameter has attribute returned!", V)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , V); return; } } while (false); | ||||
| 2050 | Check(Ty->canLosslesslyBitCastTo(FT->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
| 2051 | "Incompatible argument and return types for 'returned' attribute",do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false) | ||||
| 2052 | V)do { if (!(Ty->canLosslesslyBitCastTo(FT->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' attribute" , V); return; } } while (false); | ||||
| 2053 | SawReturned = true; | ||||
| 2054 | } | ||||
| 2055 | |||||
| 2056 | if (ArgAttrs.hasAttribute(Attribute::StructRet)) { | ||||
| 2057 | Check(!SawSRet, "Cannot have multiple 'sret' parameters!", V)do { if (!(!SawSRet)) { CheckFailed("Cannot have multiple 'sret' parameters!" , V); return; } } while (false); | ||||
| 2058 | Check(i == 0 || i == 1,do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false) | ||||
| 2059 | "Attribute 'sret' is not on first or second parameter!", V)do { if (!(i == 0 || i == 1)) { CheckFailed("Attribute 'sret' is not on first or second parameter!" , V); return; } } while (false); | ||||
| 2060 | SawSRet = true; | ||||
| 2061 | } | ||||
| 2062 | |||||
| 2063 | if (ArgAttrs.hasAttribute(Attribute::SwiftSelf)) { | ||||
| 2064 | Check(!SawSwiftSelf, "Cannot have multiple 'swiftself' parameters!", V)do { if (!(!SawSwiftSelf)) { CheckFailed("Cannot have multiple 'swiftself' parameters!" , V); return; } } while (false); | ||||
| 2065 | SawSwiftSelf = true; | ||||
| 2066 | } | ||||
| 2067 | |||||
| 2068 | if (ArgAttrs.hasAttribute(Attribute::SwiftAsync)) { | ||||
| 2069 | Check(!SawSwiftAsync, "Cannot have multiple 'swiftasync' parameters!", V)do { if (!(!SawSwiftAsync)) { CheckFailed("Cannot have multiple 'swiftasync' parameters!" , V); return; } } while (false); | ||||
| 2070 | SawSwiftAsync = true; | ||||
| 2071 | } | ||||
| 2072 | |||||
| 2073 | if (ArgAttrs.hasAttribute(Attribute::SwiftError)) { | ||||
| 2074 | Check(!SawSwiftError, "Cannot have multiple 'swifterror' parameters!", V)do { if (!(!SawSwiftError)) { CheckFailed("Cannot have multiple 'swifterror' parameters!" , V); return; } } while (false); | ||||
| 2075 | SawSwiftError = true; | ||||
| 2076 | } | ||||
| 2077 | |||||
| 2078 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) { | ||||
| 2079 | Check(i == FT->getNumParams() - 1,do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false) | ||||
| 2080 | "inalloca isn't on the last parameter!", V)do { if (!(i == FT->getNumParams() - 1)) { CheckFailed("inalloca isn't on the last parameter!" , V); return; } } while (false); | ||||
| 2081 | } | ||||
| 2082 | } | ||||
| 2083 | |||||
| 2084 | if (!Attrs.hasFnAttrs()) | ||||
| 2085 | return; | ||||
| 2086 | |||||
| 2087 | verifyAttributeTypes(Attrs.getFnAttrs(), V); | ||||
| 2088 | for (Attribute FnAttr : Attrs.getFnAttrs()) | ||||
| 2089 | Check(FnAttr.isStringAttribute() ||do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 2090 | Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()),do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 2091 | "Attribute '" + FnAttr.getAsString() +do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 2092 | "' does not apply to functions!",do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false) | ||||
| 2093 | V)do { if (!(FnAttr.isStringAttribute() || Attribute::canUseAsFnAttr (FnAttr.getKindAsEnum()))) { CheckFailed("Attribute '" + FnAttr .getAsString() + "' does not apply to functions!", V); return ; } } while (false); | ||||
| 2094 | |||||
| 2095 | Check(!(Attrs.hasFnAttr(Attribute::NoInline) &&do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 2096 | Attrs.hasFnAttr(Attribute::AlwaysInline)),do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false) | ||||
| 2097 | "Attributes 'noinline and alwaysinline' are incompatible!", V)do { if (!(!(Attrs.hasFnAttr(Attribute::NoInline) && Attrs .hasFnAttr(Attribute::AlwaysInline)))) { CheckFailed("Attributes 'noinline and alwaysinline' are incompatible!" , V); return; } } while (false); | ||||
| 2098 | |||||
| 2099 | if (Attrs.hasFnAttr(Attribute::OptimizeNone)) { | ||||
| 2100 | Check(Attrs.hasFnAttr(Attribute::NoInline),do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false) | ||||
| 2101 | "Attribute 'optnone' requires 'noinline'!", V)do { if (!(Attrs.hasFnAttr(Attribute::NoInline))) { CheckFailed ("Attribute 'optnone' requires 'noinline'!", V); return; } } while (false); | ||||
| 2102 | |||||
| 2103 | Check(!Attrs.hasFnAttr(Attribute::OptimizeForSize),do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
| 2104 | "Attributes 'optsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::OptimizeForSize))) { CheckFailed ("Attributes 'optsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
| 2105 | |||||
| 2106 | Check(!Attrs.hasFnAttr(Attribute::MinSize),do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false) | ||||
| 2107 | "Attributes 'minsize and optnone' are incompatible!", V)do { if (!(!Attrs.hasFnAttr(Attribute::MinSize))) { CheckFailed ("Attributes 'minsize and optnone' are incompatible!", V); return ; } } while (false); | ||||
| 2108 | } | ||||
| 2109 | |||||
| 2110 | if (Attrs.hasFnAttr("aarch64_pstate_sm_enabled")) { | ||||
| 2111 | Check(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
| 2112 | "Attributes 'aarch64_pstate_sm_enabled and "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
| 2113 | "aarch64_pstate_sm_compatible' are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false) | ||||
| 2114 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_sm_compatible"))) { CheckFailed("Attributes 'aarch64_pstate_sm_enabled and " "aarch64_pstate_sm_compatible' are incompatible!" , V); return; } } while (false); | ||||
| 2115 | } | ||||
| 2116 | |||||
| 2117 | if (Attrs.hasFnAttr("aarch64_pstate_za_new")) { | ||||
| 2118 | Check(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
| 2119 | "Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
| 2120 | "are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false) | ||||
| 2121 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_preserved"))) { CheckFailed("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_preserved' " "are incompatible!", V); return; } } while (false); | ||||
| 2122 | |||||
| 2123 | Check(!Attrs.hasFnAttr("aarch64_pstate_za_shared"),do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
| 2124 | "Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' "do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
| 2125 | "are incompatible!",do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false) | ||||
| 2126 | V)do { if (!(!Attrs.hasFnAttr("aarch64_pstate_za_shared"))) { CheckFailed ("Attributes 'aarch64_pstate_za_new and aarch64_pstate_za_shared' " "are incompatible!", V); return; } } while (false); | ||||
| 2127 | } | ||||
| 2128 | |||||
| 2129 | if (Attrs.hasFnAttr(Attribute::JumpTable)) { | ||||
| 2130 | const GlobalValue *GV = cast<GlobalValue>(V); | ||||
| 2131 | Check(GV->hasGlobalUnnamedAddr(),do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false) | ||||
| 2132 | "Attribute 'jumptable' requires 'unnamed_addr'", V)do { if (!(GV->hasGlobalUnnamedAddr())) { CheckFailed("Attribute 'jumptable' requires 'unnamed_addr'" , V); return; } } while (false); | ||||
| 2133 | } | ||||
| 2134 | |||||
| 2135 | if (auto Args = Attrs.getFnAttrs().getAllocSizeArgs()) { | ||||
| 2136 | auto CheckParam = [&](StringRef Name, unsigned ParamNo) { | ||||
| 2137 | if (ParamNo >= FT->getNumParams()) { | ||||
| 2138 | CheckFailed("'allocsize' " + Name + " argument is out of bounds", V); | ||||
| 2139 | return false; | ||||
| 2140 | } | ||||
| 2141 | |||||
| 2142 | if (!FT->getParamType(ParamNo)->isIntegerTy()) { | ||||
| 2143 | CheckFailed("'allocsize' " + Name + | ||||
| 2144 | " argument must refer to an integer parameter", | ||||
| 2145 | V); | ||||
| 2146 | return false; | ||||
| 2147 | } | ||||
| 2148 | |||||
| 2149 | return true; | ||||
| 2150 | }; | ||||
| 2151 | |||||
| 2152 | if (!CheckParam("element size", Args->first)) | ||||
| 2153 | return; | ||||
| 2154 | |||||
| 2155 | if (Args->second && !CheckParam("number of elements", *Args->second)) | ||||
| 2156 | return; | ||||
| 2157 | } | ||||
| 2158 | |||||
| 2159 | if (Attrs.hasFnAttr(Attribute::AllocKind)) { | ||||
| 2160 | AllocFnKind K = Attrs.getAllocKind(); | ||||
| 2161 | AllocFnKind Type = | ||||
| 2162 | K & (AllocFnKind::Alloc | AllocFnKind::Realloc | AllocFnKind::Free); | ||||
| 2163 | if (!is_contained( | ||||
| 2164 | {AllocFnKind::Alloc, AllocFnKind::Realloc, AllocFnKind::Free}, | ||||
| 2165 | Type)) | ||||
| 2166 | CheckFailed( | ||||
| 2167 | "'allockind()' requires exactly one of alloc, realloc, and free"); | ||||
| 2168 | if ((Type == AllocFnKind::Free) && | ||||
| 2169 | ((K & (AllocFnKind::Uninitialized | AllocFnKind::Zeroed | | ||||
| 2170 | AllocFnKind::Aligned)) != AllocFnKind::Unknown)) | ||||
| 2171 | CheckFailed("'allockind(\"free\")' doesn't allow uninitialized, zeroed, " | ||||
| 2172 | "or aligned modifiers."); | ||||
| 2173 | AllocFnKind ZeroedUninit = AllocFnKind::Uninitialized | AllocFnKind::Zeroed; | ||||
| 2174 | if ((K & ZeroedUninit) == ZeroedUninit) | ||||
| 2175 | CheckFailed("'allockind()' can't be both zeroed and uninitialized"); | ||||
| 2176 | } | ||||
| 2177 | |||||
| 2178 | if (Attrs.hasFnAttr(Attribute::VScaleRange)) { | ||||
| 2179 | unsigned VScaleMin = Attrs.getFnAttrs().getVScaleRangeMin(); | ||||
| 2180 | if (VScaleMin == 0) | ||||
| 2181 | CheckFailed("'vscale_range' minimum must be greater than 0", V); | ||||
| 2182 | |||||
| 2183 | std::optional<unsigned> VScaleMax = Attrs.getFnAttrs().getVScaleRangeMax(); | ||||
| 2184 | if (VScaleMax && VScaleMin > VScaleMax) | ||||
| 2185 | CheckFailed("'vscale_range' minimum cannot be greater than maximum", V); | ||||
| 2186 | } | ||||
| 2187 | |||||
| 2188 | if (Attrs.hasFnAttr("frame-pointer")) { | ||||
| 2189 | StringRef FP = Attrs.getFnAttr("frame-pointer").getValueAsString(); | ||||
| 2190 | if (FP != "all" && FP != "non-leaf" && FP != "none") | ||||
| 2191 | CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V); | ||||
| 2192 | } | ||||
| 2193 | |||||
| 2194 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V); | ||||
| 2195 | checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V); | ||||
| 2196 | checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V); | ||||
| 2197 | } | ||||
| 2198 | |||||
| 2199 | void Verifier::verifyFunctionMetadata( | ||||
| 2200 | ArrayRef<std::pair<unsigned, MDNode *>> MDs) { | ||||
| 2201 | for (const auto &Pair : MDs) { | ||||
| 2202 | if (Pair.first == LLVMContext::MD_prof) { | ||||
| 2203 | MDNode *MD = Pair.second; | ||||
| 2204 | Check(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
| 2205 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
| 2206 | |||||
| 2207 | // Check first operand. | ||||
| 2208 | Check(MD->getOperand(0) != nullptr, "first operand should not be null",do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false) | ||||
| 2209 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
| 2210 | Check(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
| 2211 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
| 2212 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
| 2213 | StringRef ProfName = MDS->getString(); | ||||
| 2214 | Check(ProfName.equals("function_entry_count") ||do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2215 | ProfName.equals("synthetic_function_entry_count"),do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2216 | "first operand should be 'function_entry_count'"do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2217 | " or 'synthetic_function_entry_count'",do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false) | ||||
| 2218 | MD)do { if (!(ProfName.equals("function_entry_count") || ProfName .equals("synthetic_function_entry_count"))) { CheckFailed("first operand should be 'function_entry_count'" " or 'synthetic_function_entry_count'", MD); return; } } while (false); | ||||
| 2219 | |||||
| 2220 | // Check second operand. | ||||
| 2221 | Check(MD->getOperand(1) != nullptr, "second operand should not be null",do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false) | ||||
| 2222 | MD)do { if (!(MD->getOperand(1) != nullptr)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
| 2223 | Check(isa<ConstantAsMetadata>(MD->getOperand(1)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false) | ||||
| 2224 | "expected integer argument to function_entry_count", MD)do { if (!(isa<ConstantAsMetadata>(MD->getOperand(1) ))) { CheckFailed("expected integer argument to function_entry_count" , MD); return; } } while (false); | ||||
| 2225 | } else if (Pair.first == LLVMContext::MD_kcfi_type) { | ||||
| 2226 | MDNode *MD = Pair.second; | ||||
| 2227 | Check(MD->getNumOperands() == 1,do { if (!(MD->getNumOperands() == 1)) { CheckFailed("!kcfi_type must have exactly one operand" , MD); return; } } while (false) | ||||
| 2228 | "!kcfi_type must have exactly one operand", MD)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("!kcfi_type must have exactly one operand" , MD); return; } } while (false); | ||||
| 2229 | Check(MD->getOperand(0) != nullptr, "!kcfi_type operand must not be null",do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("!kcfi_type operand must not be null" , MD); return; } } while (false) | ||||
| 2230 | MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("!kcfi_type operand must not be null" , MD); return; } } while (false); | ||||
| 2231 | Check(isa<ConstantAsMetadata>(MD->getOperand(0)),do { if (!(isa<ConstantAsMetadata>(MD->getOperand(0) ))) { CheckFailed("expected a constant operand for !kcfi_type" , MD); return; } } while (false) | ||||
| 2232 | "expected a constant operand for !kcfi_type", MD)do { if (!(isa<ConstantAsMetadata>(MD->getOperand(0) ))) { CheckFailed("expected a constant operand for !kcfi_type" , MD); return; } } while (false); | ||||
| 2233 | Constant *C = cast<ConstantAsMetadata>(MD->getOperand(0))->getValue(); | ||||
| 2234 | Check(isa<ConstantInt>(C),do { if (!(isa<ConstantInt>(C))) { CheckFailed("expected a constant integer operand for !kcfi_type" , MD); return; } } while (false) | ||||
| 2235 | "expected a constant integer operand for !kcfi_type", MD)do { if (!(isa<ConstantInt>(C))) { CheckFailed("expected a constant integer operand for !kcfi_type" , MD); return; } } while (false); | ||||
| 2236 | IntegerType *Type = cast<ConstantInt>(C)->getType(); | ||||
| 2237 | Check(Type->getBitWidth() == 32,do { if (!(Type->getBitWidth() == 32)) { CheckFailed("expected a 32-bit integer constant operand for !kcfi_type" , MD); return; } } while (false) | ||||
| 2238 | "expected a 32-bit integer constant operand for !kcfi_type", MD)do { if (!(Type->getBitWidth() == 32)) { CheckFailed("expected a 32-bit integer constant operand for !kcfi_type" , MD); return; } } while (false); | ||||
| 2239 | } | ||||
| 2240 | } | ||||
| 2241 | } | ||||
| 2242 | |||||
| 2243 | void Verifier::visitConstantExprsRecursively(const Constant *EntryC) { | ||||
| 2244 | if (!ConstantExprVisited.insert(EntryC).second) | ||||
| 2245 | return; | ||||
| 2246 | |||||
| 2247 | SmallVector<const Constant *, 16> Stack; | ||||
| 2248 | Stack.push_back(EntryC); | ||||
| 2249 | |||||
| 2250 | while (!Stack.empty()) { | ||||
| 2251 | const Constant *C = Stack.pop_back_val(); | ||||
| 2252 | |||||
| 2253 | // Check this constant expression. | ||||
| 2254 | if (const auto *CE = dyn_cast<ConstantExpr>(C)) | ||||
| 2255 | visitConstantExpr(CE); | ||||
| 2256 | |||||
| 2257 | if (const auto *GV = dyn_cast<GlobalValue>(C)) { | ||||
| 2258 | // Global Values get visited separately, but we do need to make sure | ||||
| 2259 | // that the global value is in the correct module | ||||
| 2260 | Check(GV->getParent() == &M, "Referencing global in another module!",do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false) | ||||
| 2261 | EntryC, &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , EntryC, &M, GV, GV->getParent()); return; } } while ( false); | ||||
| 2262 | continue; | ||||
| 2263 | } | ||||
| 2264 | |||||
| 2265 | // Visit all sub-expressions. | ||||
| 2266 | for (const Use &U : C->operands()) { | ||||
| 2267 | const auto *OpC = dyn_cast<Constant>(U); | ||||
| 2268 | if (!OpC) | ||||
| 2269 | continue; | ||||
| 2270 | if (!ConstantExprVisited.insert(OpC).second) | ||||
| 2271 | continue; | ||||
| 2272 | Stack.push_back(OpC); | ||||
| 2273 | } | ||||
| 2274 | } | ||||
| 2275 | } | ||||
| 2276 | |||||
| 2277 | void Verifier::visitConstantExpr(const ConstantExpr *CE) { | ||||
| 2278 | if (CE->getOpcode() == Instruction::BitCast) | ||||
| 2279 | Check(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
| 2280 | CE->getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false) | ||||
| 2281 | "Invalid bitcast", CE)do { if (!(CastInst::castIsValid(Instruction::BitCast, CE-> getOperand(0), CE->getType()))) { CheckFailed("Invalid bitcast" , CE); return; } } while (false); | ||||
| 2282 | } | ||||
| 2283 | |||||
| 2284 | bool Verifier::verifyAttributeCount(AttributeList Attrs, unsigned Params) { | ||||
| 2285 | // There shouldn't be more attribute sets than there are parameters plus the | ||||
| 2286 | // function and return value. | ||||
| 2287 | return Attrs.getNumAttrSets() <= Params + 2; | ||||
| 2288 | } | ||||
| 2289 | |||||
| 2290 | void Verifier::verifyInlineAsmCall(const CallBase &Call) { | ||||
| 2291 | const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand()); | ||||
| 2292 | unsigned ArgNo = 0; | ||||
| 2293 | unsigned LabelNo = 0; | ||||
| 2294 | for (const InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) { | ||||
| 2295 | if (CI.Type == InlineAsm::isLabel) { | ||||
| 2296 | ++LabelNo; | ||||
| 2297 | continue; | ||||
| 2298 | } | ||||
| 2299 | |||||
| 2300 | // Only deal with constraints that correspond to call arguments. | ||||
| 2301 | if (!CI.hasArg()) | ||||
| 2302 | continue; | ||||
| 2303 | |||||
| 2304 | if (CI.isIndirect) { | ||||
| 2305 | const Value *Arg = Call.getArgOperand(ArgNo); | ||||
| 2306 | Check(Arg->getType()->isPointerTy(),do { if (!(Arg->getType()->isPointerTy())) { CheckFailed ("Operand for indirect constraint must have pointer type", & Call); return; } } while (false) | ||||
| 2307 | "Operand for indirect constraint must have pointer type", &Call)do { if (!(Arg->getType()->isPointerTy())) { CheckFailed ("Operand for indirect constraint must have pointer type", & Call); return; } } while (false); | ||||
| 2308 | |||||
| 2309 | Check(Call.getParamElementType(ArgNo),do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false) | ||||
| 2310 | "Operand for indirect constraint must have elementtype attribute",do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false) | ||||
| 2311 | &Call)do { if (!(Call.getParamElementType(ArgNo))) { CheckFailed("Operand for indirect constraint must have elementtype attribute" , &Call); return; } } while (false); | ||||
| 2312 | } else { | ||||
| 2313 | Check(!Call.paramHasAttr(ArgNo, Attribute::ElementType),do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
| 2314 | "Elementtype attribute can only be applied for indirect "do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
| 2315 | "constraints",do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false) | ||||
| 2316 | &Call)do { if (!(!Call.paramHasAttr(ArgNo, Attribute::ElementType)) ) { CheckFailed("Elementtype attribute can only be applied for indirect " "constraints", &Call); return; } } while (false); | ||||
| 2317 | } | ||||
| 2318 | |||||
| 2319 | ArgNo++; | ||||
| 2320 | } | ||||
| 2321 | |||||
| 2322 | if (auto *CallBr = dyn_cast<CallBrInst>(&Call)) { | ||||
| 2323 | Check(LabelNo == CallBr->getNumIndirectDests(),do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false) | ||||
| 2324 | "Number of label constraints does not match number of callbr dests",do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false) | ||||
| 2325 | &Call)do { if (!(LabelNo == CallBr->getNumIndirectDests())) { CheckFailed ("Number of label constraints does not match number of callbr dests" , &Call); return; } } while (false); | ||||
| 2326 | } else { | ||||
| 2327 | Check(LabelNo == 0, "Label constraints can only be used with callbr",do { if (!(LabelNo == 0)) { CheckFailed("Label constraints can only be used with callbr" , &Call); return; } } while (false) | ||||
| 2328 | &Call)do { if (!(LabelNo == 0)) { CheckFailed("Label constraints can only be used with callbr" , &Call); return; } } while (false); | ||||
| 2329 | } | ||||
| 2330 | } | ||||
| 2331 | |||||
| 2332 | /// Verify that statepoint intrinsic is well formed. | ||||
| 2333 | void Verifier::verifyStatepoint(const CallBase &Call) { | ||||
| 2334 | assert(Call.getCalledFunction() &&(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )) | ||||
| 2335 | Call.getCalledFunction()->getIntrinsicID() ==(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )) | ||||
| 2336 | Intrinsic::experimental_gc_statepoint)(static_cast <bool> (Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint) ? void (0) : __assert_fail ("Call.getCalledFunction() && Call.getCalledFunction()->getIntrinsicID() == Intrinsic::experimental_gc_statepoint" , "llvm/lib/IR/Verifier.cpp", 2336, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 2337 | |||||
| 2338 | Check(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory() &&do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2339 | !Call.onlyAccessesArgMemory(),do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2340 | "gc.statepoint must read and write all memory to preserve "do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2341 | "reordering restrictions required by safepoint semantics",do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false) | ||||
| 2342 | Call)do { if (!(!Call.doesNotAccessMemory() && !Call.onlyReadsMemory () && !Call.onlyAccessesArgMemory())) { CheckFailed("gc.statepoint must read and write all memory to preserve " "reordering restrictions required by safepoint semantics", Call ); return; } } while (false); | ||||
| 2343 | |||||
| 2344 | const int64_t NumPatchBytes = | ||||
| 2345 | cast<ConstantInt>(Call.getArgOperand(1))->getSExtValue(); | ||||
| 2346 | assert(isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!")(static_cast <bool> (isInt<32>(NumPatchBytes) && "NumPatchBytesV is an i32!") ? void (0) : __assert_fail ("isInt<32>(NumPatchBytes) && \"NumPatchBytesV is an i32!\"" , "llvm/lib/IR/Verifier.cpp", 2346, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 2347 | Check(NumPatchBytes >= 0,do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2348 | "gc.statepoint number of patchable bytes must be "do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2349 | "positive",do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false) | ||||
| 2350 | Call)do { if (!(NumPatchBytes >= 0)) { CheckFailed("gc.statepoint number of patchable bytes must be " "positive", Call); return; } } while (false); | ||||
| 2351 | |||||
| 2352 | Type *TargetElemType = Call.getParamElementType(2); | ||||
| 2353 | Check(TargetElemType,do { if (!(TargetElemType)) { CheckFailed("gc.statepoint callee argument must have elementtype attribute" , Call); return; } } while (false) | ||||
| 2354 | "gc.statepoint callee argument must have elementtype attribute", Call)do { if (!(TargetElemType)) { CheckFailed("gc.statepoint callee argument must have elementtype attribute" , Call); return; } } while (false); | ||||
| 2355 | FunctionType *TargetFuncType = dyn_cast<FunctionType>(TargetElemType); | ||||
| 2356 | Check(TargetFuncType,do { if (!(TargetFuncType)) { CheckFailed("gc.statepoint callee elementtype must be function type" , Call); return; } } while (false) | ||||
| 2357 | "gc.statepoint callee elementtype must be function type", Call)do { if (!(TargetFuncType)) { CheckFailed("gc.statepoint callee elementtype must be function type" , Call); return; } } while (false); | ||||
| 2358 | |||||
| 2359 | const int NumCallArgs = cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue(); | ||||
| 2360 | Check(NumCallArgs >= 0,do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2361 | "gc.statepoint number of arguments to underlying call "do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2362 | "must be positive",do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false) | ||||
| 2363 | Call)do { if (!(NumCallArgs >= 0)) { CheckFailed("gc.statepoint number of arguments to underlying call " "must be positive", Call); return; } } while (false); | ||||
| 2364 | const int NumParams = (int)TargetFuncType->getNumParams(); | ||||
| 2365 | if (TargetFuncType->isVarArg()) { | ||||
| 2366 | Check(NumCallArgs >= NumParams,do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false) | ||||
| 2367 | "gc.statepoint mismatch in number of vararg call args", Call)do { if (!(NumCallArgs >= NumParams)) { CheckFailed("gc.statepoint mismatch in number of vararg call args" , Call); return; } } while (false); | ||||
| 2368 | |||||
| 2369 | // TODO: Remove this limitation | ||||
| 2370 | Check(TargetFuncType->getReturnType()->isVoidTy(),do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2371 | "gc.statepoint doesn't support wrapping non-void "do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2372 | "vararg functions yet",do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false) | ||||
| 2373 | Call)do { if (!(TargetFuncType->getReturnType()->isVoidTy()) ) { CheckFailed("gc.statepoint doesn't support wrapping non-void " "vararg functions yet", Call); return; } } while (false); | ||||
| 2374 | } else | ||||
| 2375 | Check(NumCallArgs == NumParams,do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false) | ||||
| 2376 | "gc.statepoint mismatch in number of call args", Call)do { if (!(NumCallArgs == NumParams)) { CheckFailed("gc.statepoint mismatch in number of call args" , Call); return; } } while (false); | ||||
| 2377 | |||||
| 2378 | const uint64_t Flags | ||||
| 2379 | = cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue(); | ||||
| 2380 | Check((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false) | ||||
| 2381 | "unknown flag used in gc.statepoint flags argument", Call)do { if (!((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)) { CheckFailed("unknown flag used in gc.statepoint flags argument" , Call); return; } } while (false); | ||||
| 2382 | |||||
| 2383 | // Verify that the types of the call parameter arguments match | ||||
| 2384 | // the type of the wrapped callee. | ||||
| 2385 | AttributeList Attrs = Call.getAttributes(); | ||||
| 2386 | for (int i = 0; i < NumParams; i++) { | ||||
| 2387 | Type *ParamType = TargetFuncType->getParamType(i); | ||||
| 2388 | Type *ArgType = Call.getArgOperand(5 + i)->getType(); | ||||
| 2389 | Check(ArgType == ParamType,do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2390 | "gc.statepoint call argument does not match wrapped "do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2391 | "function type",do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false) | ||||
| 2392 | Call)do { if (!(ArgType == ParamType)) { CheckFailed("gc.statepoint call argument does not match wrapped " "function type", Call); return; } } while (false); | ||||
| 2393 | |||||
| 2394 | if (TargetFuncType->isVarArg()) { | ||||
| 2395 | AttributeSet ArgAttrs = Attrs.getParamAttrs(5 + i); | ||||
| 2396 | Check(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 2397 | "Attribute 'sret' cannot be used for vararg call arguments!", Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
| 2398 | } | ||||
| 2399 | } | ||||
| 2400 | |||||
| 2401 | const int EndCallArgsInx = 4 + NumCallArgs; | ||||
| 2402 | |||||
| 2403 | const Value *NumTransitionArgsV = Call.getArgOperand(EndCallArgsInx + 1); | ||||
| 2404 | Check(isa<ConstantInt>(NumTransitionArgsV),do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2405 | "gc.statepoint number of transition arguments "do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2406 | "must be constant integer",do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2407 | Call)do { if (!(isa<ConstantInt>(NumTransitionArgsV))) { CheckFailed ("gc.statepoint number of transition arguments " "must be constant integer" , Call); return; } } while (false); | ||||
| 2408 | const int NumTransitionArgs = | ||||
| 2409 | cast<ConstantInt>(NumTransitionArgsV)->getZExtValue(); | ||||
| 2410 | Check(NumTransitionArgs == 0,do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false) | ||||
| 2411 | "gc.statepoint w/inline transition bundle is deprecated", Call)do { if (!(NumTransitionArgs == 0)) { CheckFailed("gc.statepoint w/inline transition bundle is deprecated" , Call); return; } } while (false); | ||||
| 2412 | const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; | ||||
| 2413 | |||||
| 2414 | const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); | ||||
| 2415 | Check(isa<ConstantInt>(NumDeoptArgsV),do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2416 | "gc.statepoint number of deoptimization arguments "do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2417 | "must be constant integer",do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false) | ||||
| 2418 | Call)do { if (!(isa<ConstantInt>(NumDeoptArgsV))) { CheckFailed ("gc.statepoint number of deoptimization arguments " "must be constant integer" , Call); return; } } while (false); | ||||
| 2419 | const int NumDeoptArgs = cast<ConstantInt>(NumDeoptArgsV)->getZExtValue(); | ||||
| 2420 | Check(NumDeoptArgs == 0,do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false) | ||||
| 2421 | "gc.statepoint w/inline deopt operands is deprecated", Call)do { if (!(NumDeoptArgs == 0)) { CheckFailed("gc.statepoint w/inline deopt operands is deprecated" , Call); return; } } while (false); | ||||
| 2422 | |||||
| 2423 | const int ExpectedNumArgs = 7 + NumCallArgs; | ||||
| 2424 | Check(ExpectedNumArgs == (int)Call.arg_size(),do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false) | ||||
| 2425 | "gc.statepoint too many arguments", Call)do { if (!(ExpectedNumArgs == (int)Call.arg_size())) { CheckFailed ("gc.statepoint too many arguments", Call); return; } } while (false); | ||||
| 2426 | |||||
| 2427 | // Check that the only uses of this gc.statepoint are gc.result or | ||||
| 2428 | // gc.relocate calls which are tied to this statepoint and thus part | ||||
| 2429 | // of the same statepoint sequence | ||||
| 2430 | for (const User *U : Call.users()) { | ||||
| 2431 | const CallInst *UserCall = dyn_cast<const CallInst>(U); | ||||
| 2432 | Check(UserCall, "illegal use of statepoint token", Call, U)do { if (!(UserCall)) { CheckFailed("illegal use of statepoint token" , Call, U); return; } } while (false); | ||||
| 2433 | if (!UserCall) | ||||
| 2434 | continue; | ||||
| 2435 | Check(isa<GCRelocateInst>(UserCall) || isa<GCResultInst>(UserCall),do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2436 | "gc.result or gc.relocate are the only value uses "do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2437 | "of a gc.statepoint",do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false) | ||||
| 2438 | Call, U)do { if (!(isa<GCRelocateInst>(UserCall) || isa<GCResultInst >(UserCall))) { CheckFailed("gc.result or gc.relocate are the only value uses " "of a gc.statepoint", Call, U); return; } } while (false); | ||||
| 2439 | if (isa<GCResultInst>(UserCall)) { | ||||
| 2440 | Check(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
| 2441 | "gc.result connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.result connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
| 2442 | } else if (isa<GCRelocateInst>(Call)) { | ||||
| 2443 | Check(UserCall->getArgOperand(0) == &Call,do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false) | ||||
| 2444 | "gc.relocate connected to wrong gc.statepoint", Call, UserCall)do { if (!(UserCall->getArgOperand(0) == &Call)) { CheckFailed ("gc.relocate connected to wrong gc.statepoint", Call, UserCall ); return; } } while (false); | ||||
| 2445 | } | ||||
| 2446 | } | ||||
| 2447 | |||||
| 2448 | // Note: It is legal for a single derived pointer to be listed multiple | ||||
| 2449 | // times. It's non-optimal, but it is legal. It can also happen after | ||||
| 2450 | // insertion if we strip a bitcast away. | ||||
| 2451 | // Note: It is really tempting to check that each base is relocated and | ||||
| 2452 | // that a derived pointer is never reused as a base pointer. This turns | ||||
| 2453 | // out to be problematic since optimizations run after safepoint insertion | ||||
| 2454 | // can recognize equality properties that the insertion logic doesn't know | ||||
| 2455 | // about. See example statepoint.ll in the verifier subdirectory | ||||
| 2456 | } | ||||
| 2457 | |||||
| 2458 | void Verifier::verifyFrameRecoverIndices() { | ||||
| 2459 | for (auto &Counts : FrameEscapeInfo) { | ||||
| 2460 | Function *F = Counts.first; | ||||
| 2461 | unsigned EscapedObjectCount = Counts.second.first; | ||||
| 2462 | unsigned MaxRecoveredIndex = Counts.second.second; | ||||
| 2463 | Check(MaxRecoveredIndex <= EscapedObjectCount,do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2464 | "all indices passed to llvm.localrecover must be less than the "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2465 | "number of arguments passed to llvm.localescape in the parent "do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2466 | "function",do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false) | ||||
| 2467 | F)do { if (!(MaxRecoveredIndex <= EscapedObjectCount)) { CheckFailed ("all indices passed to llvm.localrecover must be less than the " "number of arguments passed to llvm.localescape in the parent " "function", F); return; } } while (false); | ||||
| 2468 | } | ||||
| 2469 | } | ||||
| 2470 | |||||
| 2471 | static Instruction *getSuccPad(Instruction *Terminator) { | ||||
| 2472 | BasicBlock *UnwindDest; | ||||
| 2473 | if (auto *II = dyn_cast<InvokeInst>(Terminator)) | ||||
| 2474 | UnwindDest = II->getUnwindDest(); | ||||
| 2475 | else if (auto *CSI = dyn_cast<CatchSwitchInst>(Terminator)) | ||||
| 2476 | UnwindDest = CSI->getUnwindDest(); | ||||
| 2477 | else | ||||
| 2478 | UnwindDest = cast<CleanupReturnInst>(Terminator)->getUnwindDest(); | ||||
| 2479 | return UnwindDest->getFirstNonPHI(); | ||||
| 2480 | } | ||||
| 2481 | |||||
| 2482 | void Verifier::verifySiblingFuncletUnwinds() { | ||||
| 2483 | SmallPtrSet<Instruction *, 8> Visited; | ||||
| 2484 | SmallPtrSet<Instruction *, 8> Active; | ||||
| 2485 | for (const auto &Pair : SiblingFuncletInfo) { | ||||
| 2486 | Instruction *PredPad = Pair.first; | ||||
| 2487 | if (Visited.count(PredPad)) | ||||
| 2488 | continue; | ||||
| 2489 | Active.insert(PredPad); | ||||
| 2490 | Instruction *Terminator = Pair.second; | ||||
| 2491 | do { | ||||
| 2492 | Instruction *SuccPad = getSuccPad(Terminator); | ||||
| 2493 | if (Active.count(SuccPad)) { | ||||
| 2494 | // Found a cycle; report error | ||||
| 2495 | Instruction *CyclePad = SuccPad; | ||||
| 2496 | SmallVector<Instruction *, 8> CycleNodes; | ||||
| 2497 | do { | ||||
| 2498 | CycleNodes.push_back(CyclePad); | ||||
| 2499 | Instruction *CycleTerminator = SiblingFuncletInfo[CyclePad]; | ||||
| 2500 | if (CycleTerminator != CyclePad) | ||||
| 2501 | CycleNodes.push_back(CycleTerminator); | ||||
| 2502 | CyclePad = getSuccPad(CycleTerminator); | ||||
| 2503 | } while (CyclePad != SuccPad); | ||||
| 2504 | Check(false, "EH pads can't handle each other's exceptions",do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false) | ||||
| 2505 | ArrayRef<Instruction *>(CycleNodes))do { if (!(false)) { CheckFailed("EH pads can't handle each other's exceptions" , ArrayRef<Instruction *>(CycleNodes)); return; } } while (false); | ||||
| 2506 | } | ||||
| 2507 | // Don't re-walk a node we've already checked | ||||
| 2508 | if (!Visited.insert(SuccPad).second) | ||||
| 2509 | break; | ||||
| 2510 | // Walk to this successor if it has a map entry. | ||||
| 2511 | PredPad = SuccPad; | ||||
| 2512 | auto TermI = SiblingFuncletInfo.find(PredPad); | ||||
| 2513 | if (TermI == SiblingFuncletInfo.end()) | ||||
| 2514 | break; | ||||
| 2515 | Terminator = TermI->second; | ||||
| 2516 | Active.insert(PredPad); | ||||
| 2517 | } while (true); | ||||
| 2518 | // Each node only has one successor, so we've walked all the active | ||||
| 2519 | // nodes' successors. | ||||
| 2520 | Active.clear(); | ||||
| 2521 | } | ||||
| 2522 | } | ||||
| 2523 | |||||
| 2524 | // visitFunction - Verify that a function is ok. | ||||
| 2525 | // | ||||
| 2526 | void Verifier::visitFunction(const Function &F) { | ||||
| 2527 | visitGlobalValue(F); | ||||
| 2528 | |||||
| 2529 | // Check function arguments. | ||||
| 2530 | FunctionType *FT = F.getFunctionType(); | ||||
| 2531 | unsigned NumArgs = F.arg_size(); | ||||
| 2532 | |||||
| 2533 | Check(&Context == &F.getContext(),do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false) | ||||
| |||||
| 2534 | "Function context does not match Module context!", &F)do { if (!(&Context == &F.getContext())) { CheckFailed ("Function context does not match Module context!", &F); return ; } } while (false); | ||||
| 2535 | |||||
| 2536 | Check(!F.hasCommonLinkage(), "Functions may not have common linkage", &F)do { if (!(!F.hasCommonLinkage())) { CheckFailed("Functions may not have common linkage" , &F); return; } } while (false); | ||||
| 2537 | Check(FT->getNumParams() == NumArgs,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
| 2538 | "# formal arguments must match # of arguments for function type!", &F,do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false) | ||||
| 2539 | FT)do { if (!(FT->getNumParams() == NumArgs)) { CheckFailed("# formal arguments must match # of arguments for function type!" , &F, FT); return; } } while (false); | ||||
| 2540 | Check(F.getReturnType()->isFirstClassType() ||do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
| 2541 | F.getReturnType()->isVoidTy() || F.getReturnType()->isStructTy(),do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false) | ||||
| 2542 | "Functions cannot return aggregate values!", &F)do { if (!(F.getReturnType()->isFirstClassType() || F.getReturnType ()->isVoidTy() || F.getReturnType()->isStructTy())) { CheckFailed ("Functions cannot return aggregate values!", &F); return ; } } while (false); | ||||
| 2543 | |||||
| 2544 | Check(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(),do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false) | ||||
| 2545 | "Invalid struct return type!", &F)do { if (!(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy ())) { CheckFailed("Invalid struct return type!", &F); return ; } } while (false); | ||||
| 2546 | |||||
| 2547 | AttributeList Attrs = F.getAttributes(); | ||||
| 2548 | |||||
| 2549 | Check(verifyAttributeCount(Attrs, FT->getNumParams()),do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false) | ||||
| 2550 | "Attribute after last parameter!", &F)do { if (!(verifyAttributeCount(Attrs, FT->getNumParams()) )) { CheckFailed("Attribute after last parameter!", &F); return ; } } while (false); | ||||
| 2551 | |||||
| 2552 | bool IsIntrinsic = F.isIntrinsic(); | ||||
| 2553 | |||||
| 2554 | // Check function attributes. | ||||
| 2555 | verifyFunctionAttrs(FT, Attrs, &F, IsIntrinsic, /* IsInlineAsm */ false); | ||||
| 2556 | |||||
| 2557 | // On function declarations/definitions, we do not support the builtin | ||||
| 2558 | // attribute. We do not check this in VerifyFunctionAttrs since that is | ||||
| 2559 | // checking for Attributes that can/can not ever be on functions. | ||||
| 2560 | Check(!Attrs.hasFnAttr(Attribute::Builtin),do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false) | ||||
| 2561 | "Attribute 'builtin' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasFnAttr(Attribute::Builtin))) { CheckFailed ("Attribute 'builtin' can only be applied to a callsite.", & F); return; } } while (false); | ||||
| 2562 | |||||
| 2563 | Check(!Attrs.hasAttrSomewhere(Attribute::ElementType),do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false) | ||||
| 2564 | "Attribute 'elementtype' can only be applied to a callsite.", &F)do { if (!(!Attrs.hasAttrSomewhere(Attribute::ElementType))) { CheckFailed("Attribute 'elementtype' can only be applied to a callsite." , &F); return; } } while (false); | ||||
| 2565 | |||||
| 2566 | // Check that this function meets the restrictions on this calling convention. | ||||
| 2567 | // Sometimes varargs is used for perfectly forwarding thunks, so some of these | ||||
| 2568 | // restrictions can be lifted. | ||||
| 2569 | switch (F.getCallingConv()) { | ||||
| 2570 | default: | ||||
| 2571 | case CallingConv::C: | ||||
| 2572 | break; | ||||
| 2573 | case CallingConv::X86_INTR: { | ||||
| 2574 | Check(F.arg_empty() || Attrs.hasParamAttr(0, Attribute::ByVal),do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false) | ||||
| 2575 | "Calling convention parameter requires byval", &F)do { if (!(F.arg_empty() || Attrs.hasParamAttr(0, Attribute:: ByVal))) { CheckFailed("Calling convention parameter requires byval" , &F); return; } } while (false); | ||||
| 2576 | break; | ||||
| 2577 | } | ||||
| 2578 | case CallingConv::AMDGPU_KERNEL: | ||||
| 2579 | case CallingConv::SPIR_KERNEL: | ||||
| 2580 | Check(F.getReturnType()->isVoidTy(),do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false) | ||||
| 2581 | "Calling convention requires void return type", &F)do { if (!(F.getReturnType()->isVoidTy())) { CheckFailed("Calling convention requires void return type" , &F); return; } } while (false); | ||||
| 2582 | [[fallthrough]]; | ||||
| 2583 | case CallingConv::AMDGPU_VS: | ||||
| 2584 | case CallingConv::AMDGPU_HS: | ||||
| 2585 | case CallingConv::AMDGPU_GS: | ||||
| 2586 | case CallingConv::AMDGPU_PS: | ||||
| 2587 | case CallingConv::AMDGPU_CS: | ||||
| 2588 | Check(!F.hasStructRetAttr(), "Calling convention does not allow sret", &F)do { if (!(!F.hasStructRetAttr())) { CheckFailed("Calling convention does not allow sret" , &F); return; } } while (false); | ||||
| 2589 | if (F.getCallingConv() != CallingConv::SPIR_KERNEL) { | ||||
| 2590 | const unsigned StackAS = DL.getAllocaAddrSpace(); | ||||
| 2591 | unsigned i = 0; | ||||
| 2592 | for (const Argument &Arg : F.args()) { | ||||
| 2593 | Check(!Attrs.hasParamAttr(i, Attribute::ByVal),do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false) | ||||
| 2594 | "Calling convention disallows byval", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::ByVal))) { CheckFailed ("Calling convention disallows byval", &F); return; } } while (false); | ||||
| 2595 | Check(!Attrs.hasParamAttr(i, Attribute::Preallocated),do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false) | ||||
| 2596 | "Calling convention disallows preallocated", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::Preallocated))) { CheckFailed("Calling convention disallows preallocated", & F); return; } } while (false); | ||||
| 2597 | Check(!Attrs.hasParamAttr(i, Attribute::InAlloca),do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false) | ||||
| 2598 | "Calling convention disallows inalloca", &F)do { if (!(!Attrs.hasParamAttr(i, Attribute::InAlloca))) { CheckFailed ("Calling convention disallows inalloca", &F); return; } } while (false); | ||||
| 2599 | |||||
| 2600 | if (Attrs.hasParamAttr(i, Attribute::ByRef)) { | ||||
| 2601 | // FIXME: Should also disallow LDS and GDS, but we don't have the enum | ||||
| 2602 | // value here. | ||||
| 2603 | Check(Arg.getType()->getPointerAddressSpace() != StackAS,do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false) | ||||
| 2604 | "Calling convention disallows stack byref", &F)do { if (!(Arg.getType()->getPointerAddressSpace() != StackAS )) { CheckFailed("Calling convention disallows stack byref", & F); return; } } while (false); | ||||
| 2605 | } | ||||
| 2606 | |||||
| 2607 | ++i; | ||||
| 2608 | } | ||||
| 2609 | } | ||||
| 2610 | |||||
| 2611 | [[fallthrough]]; | ||||
| 2612 | case CallingConv::Fast: | ||||
| 2613 | case CallingConv::Cold: | ||||
| 2614 | case CallingConv::Intel_OCL_BI: | ||||
| 2615 | case CallingConv::PTX_Kernel: | ||||
| 2616 | case CallingConv::PTX_Device: | ||||
| 2617 | Check(!F.isVarArg(),do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
| 2618 | "Calling convention does not support varargs or "do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
| 2619 | "perfect forwarding!",do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false) | ||||
| 2620 | &F)do { if (!(!F.isVarArg())) { CheckFailed("Calling convention does not support varargs or " "perfect forwarding!", &F); return; } } while (false); | ||||
| 2621 | break; | ||||
| 2622 | } | ||||
| 2623 | |||||
| 2624 | // Check that the argument values match the function type for this function... | ||||
| 2625 | unsigned i = 0; | ||||
| 2626 | for (const Argument &Arg : F.args()) { | ||||
| 2627 | Check(Arg.getType() == FT->getParamType(i),do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
| 2628 | "Argument value does not match function argument type!", &Arg,do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false) | ||||
| 2629 | FT->getParamType(i))do { if (!(Arg.getType() == FT->getParamType(i))) { CheckFailed ("Argument value does not match function argument type!", & Arg, FT->getParamType(i)); return; } } while (false); | ||||
| 2630 | Check(Arg.getType()->isFirstClassType(),do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false) | ||||
| 2631 | "Function arguments must have first-class types!", &Arg)do { if (!(Arg.getType()->isFirstClassType())) { CheckFailed ("Function arguments must have first-class types!", &Arg) ; return; } } while (false); | ||||
| 2632 | if (!IsIntrinsic) { | ||||
| 2633 | Check(!Arg.getType()->isMetadataTy(),do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false) | ||||
| 2634 | "Function takes metadata but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isMetadataTy())) { CheckFailed( "Function takes metadata but isn't an intrinsic", &Arg, & F); return; } } while (false); | ||||
| 2635 | Check(!Arg.getType()->isTokenTy(),do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
| 2636 | "Function takes token but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isTokenTy())) { CheckFailed("Function takes token but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
| 2637 | Check(!Arg.getType()->isX86_AMXTy(),do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false) | ||||
| 2638 | "Function takes x86_amx but isn't an intrinsic", &Arg, &F)do { if (!(!Arg.getType()->isX86_AMXTy())) { CheckFailed("Function takes x86_amx but isn't an intrinsic" , &Arg, &F); return; } } while (false); | ||||
| 2639 | } | ||||
| 2640 | |||||
| 2641 | // Check that swifterror argument is only used by loads and stores. | ||||
| 2642 | if (Attrs.hasParamAttr(i, Attribute::SwiftError)) { | ||||
| 2643 | verifySwiftErrorValue(&Arg); | ||||
| 2644 | } | ||||
| 2645 | ++i; | ||||
| 2646 | } | ||||
| 2647 | |||||
| 2648 | if (!IsIntrinsic) { | ||||
| 2649 | Check(!F.getReturnType()->isTokenTy(),do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false) | ||||
| 2650 | "Function returns a token but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isTokenTy())) { CheckFailed ("Function returns a token but isn't an intrinsic", &F); return ; } } while (false); | ||||
| 2651 | Check(!F.getReturnType()->isX86_AMXTy(),do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false) | ||||
| 2652 | "Function returns a x86_amx but isn't an intrinsic", &F)do { if (!(!F.getReturnType()->isX86_AMXTy())) { CheckFailed ("Function returns a x86_amx but isn't an intrinsic", &F) ; return; } } while (false); | ||||
| 2653 | } | ||||
| 2654 | |||||
| 2655 | // Get the function metadata attachments. | ||||
| 2656 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
| 2657 | F.getAllMetadata(MDs); | ||||
| 2658 | assert(F.hasMetadata() != MDs.empty() && "Bit out-of-sync")(static_cast <bool> (F.hasMetadata() != MDs.empty() && "Bit out-of-sync") ? void (0) : __assert_fail ("F.hasMetadata() != MDs.empty() && \"Bit out-of-sync\"" , "llvm/lib/IR/Verifier.cpp", 2658, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 2659 | verifyFunctionMetadata(MDs); | ||||
| 2660 | |||||
| 2661 | // Check validity of the personality function | ||||
| 2662 | if (F.hasPersonalityFn()) { | ||||
| 2663 | auto *Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); | ||||
| 2664 | if (Per) | ||||
| 2665 | Check(Per->getParent() == F.getParent(),do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
| 2666 | "Referencing personality function in another module!", &F,do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false) | ||||
| 2667 | F.getParent(), Per, Per->getParent())do { if (!(Per->getParent() == F.getParent())) { CheckFailed ("Referencing personality function in another module!", & F, F.getParent(), Per, Per->getParent()); return; } } while (false); | ||||
| 2668 | } | ||||
| 2669 | |||||
| 2670 | // EH funclet coloring can be expensive, recompute on-demand | ||||
| 2671 | BlockEHFuncletColors.clear(); | ||||
| 2672 | |||||
| 2673 | if (F.isMaterializable()) { | ||||
| 2674 | // Function has a body somewhere we can't see. | ||||
| 2675 | Check(MDs.empty(), "unmaterialized function cannot have metadata", &F,do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false) | ||||
| 2676 | MDs.empty() ? nullptr : MDs.front().second)do { if (!(MDs.empty())) { CheckFailed("unmaterialized function cannot have metadata" , &F, MDs.empty() ? nullptr : MDs.front().second); return ; } } while (false); | ||||
| 2677 | } else if (F.isDeclaration()) { | ||||
| 2678 | for (const auto &I : MDs) { | ||||
| 2679 | // This is used for call site debug information. | ||||
| 2680 | CheckDI(I.first != LLVMContext::MD_dbg ||do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2681 | !cast<DISubprogram>(I.second)->isDistinct(),do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2682 | "function declaration may only have a unique !dbg attachment",do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false) | ||||
| 2683 | &F)do { if (!(I.first != LLVMContext::MD_dbg || !cast<DISubprogram >(I.second)->isDistinct())) { DebugInfoCheckFailed("function declaration may only have a unique !dbg attachment" , &F); return; } } while (false); | ||||
| 2684 | Check(I.first != LLVMContext::MD_prof,do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false) | ||||
| 2685 | "function declaration may not have a !prof attachment", &F)do { if (!(I.first != LLVMContext::MD_prof)) { CheckFailed("function declaration may not have a !prof attachment" , &F); return; } } while (false); | ||||
| 2686 | |||||
| 2687 | // Verify the metadata itself. | ||||
| 2688 | visitMDNode(*I.second, AreDebugLocsAllowed::Yes); | ||||
| 2689 | } | ||||
| 2690 | Check(!F.hasPersonalityFn(),do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false) | ||||
| 2691 | "Function declaration shouldn't have a personality routine", &F)do { if (!(!F.hasPersonalityFn())) { CheckFailed("Function declaration shouldn't have a personality routine" , &F); return; } } while (false); | ||||
| 2692 | } else { | ||||
| 2693 | // Verify that this function (which has a body) is not named "llvm.*". It | ||||
| 2694 | // is not legal to define intrinsics. | ||||
| 2695 | Check(!IsIntrinsic, "llvm intrinsics cannot be defined!", &F)do { if (!(!IsIntrinsic)) { CheckFailed("llvm intrinsics cannot be defined!" , &F); return; } } while (false); | ||||
| 2696 | |||||
| 2697 | // Check the entry node | ||||
| 2698 | const BasicBlock *Entry = &F.getEntryBlock(); | ||||
| 2699 | Check(pred_empty(Entry),do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false) | ||||
| 2700 | "Entry block to function must not have predecessors!", Entry)do { if (!(pred_empty(Entry))) { CheckFailed("Entry block to function must not have predecessors!" , Entry); return; } } while (false); | ||||
| 2701 | |||||
| 2702 | // The address of the entry block cannot be taken, unless it is dead. | ||||
| 2703 | if (Entry->hasAddressTaken()) { | ||||
| 2704 | Check(!BlockAddress::lookup(Entry)->isConstantUsed(),do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false) | ||||
| 2705 | "blockaddress may not be used with the entry block!", Entry)do { if (!(!BlockAddress::lookup(Entry)->isConstantUsed()) ) { CheckFailed("blockaddress may not be used with the entry block!" , Entry); return; } } while (false); | ||||
| 2706 | } | ||||
| 2707 | |||||
| 2708 | unsigned NumDebugAttachments = 0, NumProfAttachments = 0, | ||||
| 2709 | NumKCFIAttachments = 0; | ||||
| 2710 | // Visit metadata attachments. | ||||
| 2711 | for (const auto &I : MDs) { | ||||
| 2712 | // Verify that the attachment is legal. | ||||
| 2713 | auto AllowLocs = AreDebugLocsAllowed::No; | ||||
| 2714 | switch (I.first) { | ||||
| 2715 | default: | ||||
| 2716 | break; | ||||
| 2717 | case LLVMContext::MD_dbg: { | ||||
| 2718 | ++NumDebugAttachments; | ||||
| 2719 | CheckDI(NumDebugAttachments == 1,do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false) | ||||
| 2720 | "function must have a single !dbg attachment", &F, I.second)do { if (!(NumDebugAttachments == 1)) { DebugInfoCheckFailed( "function must have a single !dbg attachment", &F, I.second ); return; } } while (false); | ||||
| 2721 | CheckDI(isa<DISubprogram>(I.second),do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false) | ||||
| 2722 | "function !dbg attachment must be a subprogram", &F, I.second)do { if (!(isa<DISubprogram>(I.second))) { DebugInfoCheckFailed ("function !dbg attachment must be a subprogram", &F, I.second ); return; } } while (false); | ||||
| 2723 | CheckDI(cast<DISubprogram>(I.second)->isDistinct(),do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
| 2724 | "function definition may only have a distinct !dbg attachment",do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false) | ||||
| 2725 | &F)do { if (!(cast<DISubprogram>(I.second)->isDistinct( ))) { DebugInfoCheckFailed("function definition may only have a distinct !dbg attachment" , &F); return; } } while (false); | ||||
| 2726 | |||||
| 2727 | auto *SP = cast<DISubprogram>(I.second); | ||||
| 2728 | const Function *&AttachedTo = DISubprogramAttachments[SP]; | ||||
| 2729 | CheckDI(!AttachedTo || AttachedTo == &F,do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false) | ||||
| 2730 | "DISubprogram attached to more than one function", SP, &F)do { if (!(!AttachedTo || AttachedTo == &F)) { DebugInfoCheckFailed ("DISubprogram attached to more than one function", SP, & F); return; } } while (false); | ||||
| 2731 | AttachedTo = &F; | ||||
| 2732 | AllowLocs = AreDebugLocsAllowed::Yes; | ||||
| 2733 | break; | ||||
| 2734 | } | ||||
| 2735 | case LLVMContext::MD_prof: | ||||
| 2736 | ++NumProfAttachments; | ||||
| 2737 | Check(NumProfAttachments == 1,do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false) | ||||
| 2738 | "function must have a single !prof attachment", &F, I.second)do { if (!(NumProfAttachments == 1)) { CheckFailed("function must have a single !prof attachment" , &F, I.second); return; } } while (false); | ||||
| 2739 | break; | ||||
| 2740 | case LLVMContext::MD_kcfi_type: | ||||
| 2741 | ++NumKCFIAttachments; | ||||
| 2742 | Check(NumKCFIAttachments == 1,do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false) | ||||
| 2743 | "function must have a single !kcfi_type attachment", &F,do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false) | ||||
| 2744 | I.second)do { if (!(NumKCFIAttachments == 1)) { CheckFailed("function must have a single !kcfi_type attachment" , &F, I.second); return; } } while (false); | ||||
| 2745 | break; | ||||
| 2746 | } | ||||
| 2747 | |||||
| 2748 | // Verify the metadata itself. | ||||
| 2749 | visitMDNode(*I.second, AllowLocs); | ||||
| 2750 | } | ||||
| 2751 | } | ||||
| 2752 | |||||
| 2753 | // If this function is actually an intrinsic, verify that it is only used in | ||||
| 2754 | // direct call/invokes, never having its "address taken". | ||||
| 2755 | // Only do this if the module is materialized, otherwise we don't have all the | ||||
| 2756 | // uses. | ||||
| 2757 | if (F.isIntrinsic() && F.getParent()->isMaterialized()) { | ||||
| 2758 | const User *U; | ||||
| 2759 | if (F.hasAddressTaken(&U, false, true, false, | ||||
| 2760 | /*IgnoreARCAttachedCall=*/true)) | ||||
| 2761 | Check(false, "Invalid user of intrinsic instruction!", U)do { if (!(false)) { CheckFailed("Invalid user of intrinsic instruction!" , U); return; } } while (false); | ||||
| 2762 | } | ||||
| 2763 | |||||
| 2764 | // Check intrinsics' signatures. | ||||
| 2765 | switch (F.getIntrinsicID()) { | ||||
| 2766 | case Intrinsic::experimental_gc_get_pointer_base: { | ||||
| 2767 | FunctionType *FT = F.getFunctionType(); | ||||
| 2768 | Check(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
| 2769 | Check(isa<PointerType>(F.getReturnType()),do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false) | ||||
| 2770 | "gc.get.pointer.base must return a pointer", F)do { if (!(isa<PointerType>(F.getReturnType()))) { CheckFailed ("gc.get.pointer.base must return a pointer", F); return; } } while (false); | ||||
| 2771 | Check(FT->getParamType(0) == F.getReturnType(),do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false) | ||||
| 2772 | "gc.get.pointer.base operand and result must be of the same type", F)do { if (!(FT->getParamType(0) == F.getReturnType())) { CheckFailed ("gc.get.pointer.base operand and result must be of the same type" , F); return; } } while (false); | ||||
| 2773 | break; | ||||
| 2774 | } | ||||
| 2775 | case Intrinsic::experimental_gc_get_pointer_offset: { | ||||
| 2776 | FunctionType *FT = F.getFunctionType(); | ||||
| 2777 | Check(FT->getNumParams() == 1, "wrong number of parameters", F)do { if (!(FT->getNumParams() == 1)) { CheckFailed("wrong number of parameters" , F); return; } } while (false); | ||||
| 2778 | Check(isa<PointerType>(FT->getParamType(0)),do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false) | ||||
| 2779 | "gc.get.pointer.offset operand must be a pointer", F)do { if (!(isa<PointerType>(FT->getParamType(0)))) { CheckFailed("gc.get.pointer.offset operand must be a pointer" , F); return; } } while (false); | ||||
| 2780 | Check(F.getReturnType()->isIntegerTy(),do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false) | ||||
| 2781 | "gc.get.pointer.offset must return integer", F)do { if (!(F.getReturnType()->isIntegerTy())) { CheckFailed ("gc.get.pointer.offset must return integer", F); return; } } while (false); | ||||
| 2782 | break; | ||||
| 2783 | } | ||||
| 2784 | } | ||||
| 2785 | |||||
| 2786 | auto *N = F.getSubprogram(); | ||||
| 2787 | HasDebugInfo = (N != nullptr); | ||||
| 2788 | if (!HasDebugInfo
| ||||
| 2789 | return; | ||||
| 2790 | |||||
| 2791 | // Check that all !dbg attachments lead to back to N. | ||||
| 2792 | // | ||||
| 2793 | // FIXME: Check this incrementally while visiting !dbg attachments. | ||||
| 2794 | // FIXME: Only check when N is the canonical subprogram for F. | ||||
| 2795 | SmallPtrSet<const MDNode *, 32> Seen; | ||||
| 2796 | auto VisitDebugLoc = [&](const Instruction &I, const MDNode *Node) { | ||||
| 2797 | // Be careful about using DILocation here since we might be dealing with | ||||
| 2798 | // broken code (this is the Verifier after all). | ||||
| 2799 | const DILocation *DL = dyn_cast_or_null<DILocation>(Node); | ||||
| 2800 | if (!DL
| ||||
| 2801 | return; | ||||
| 2802 | if (!Seen.insert(DL).second) | ||||
| 2803 | return; | ||||
| 2804 | |||||
| 2805 | Metadata *Parent = DL->getRawScope(); | ||||
| 2806 | CheckDI(Parent && isa<DILocalScope>(Parent),do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false) | ||||
| 2807 | "DILocation's scope must be a DILocalScope", N, &F, &I, DL, Parent)do { if (!(Parent && isa<DILocalScope>(Parent)) ) { DebugInfoCheckFailed("DILocation's scope must be a DILocalScope" , N, &F, &I, DL, Parent); return; } } while (false); | ||||
| 2808 | |||||
| 2809 | DILocalScope *Scope = DL->getInlinedAtScope(); | ||||
| 2810 | Check(Scope, "Failed to find DILocalScope", DL)do { if (!(Scope)) { CheckFailed("Failed to find DILocalScope" , DL); return; } } while (false); | ||||
| 2811 | |||||
| 2812 | if (!Seen.insert(Scope).second) | ||||
| 2813 | return; | ||||
| 2814 | |||||
| 2815 | DISubprogram *SP = Scope->getSubprogram(); | ||||
| 2816 | |||||
| 2817 | // Scope and SP could be the same MDNode and we don't want to skip | ||||
| 2818 | // validation in that case | ||||
| 2819 | if (SP && ((Scope != SP) && !Seen.insert(SP).second)) | ||||
| 2820 | return; | ||||
| 2821 | |||||
| 2822 | CheckDI(SP->describes(&F),do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
| |||||
| 2823 | "!dbg attachment points at wrong subprogram for function", N, &F,do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false) | ||||
| 2824 | &I, DL, Scope, SP)do { if (!(SP->describes(&F))) { DebugInfoCheckFailed( "!dbg attachment points at wrong subprogram for function", N, &F, &I, DL, Scope, SP); return; } } while (false); | ||||
| 2825 | }; | ||||
| 2826 | for (auto &BB : F) | ||||
| 2827 | for (auto &I : BB) { | ||||
| 2828 | VisitDebugLoc(I, I.getDebugLoc().getAsMDNode()); | ||||
| 2829 | // The llvm.loop annotations also contain two DILocations. | ||||
| 2830 | if (auto MD = I.getMetadata(LLVMContext::MD_loop)) | ||||
| 2831 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) | ||||
| 2832 | VisitDebugLoc(I, dyn_cast_or_null<MDNode>(MD->getOperand(i))); | ||||
| 2833 | if (BrokenDebugInfo) | ||||
| 2834 | return; | ||||
| 2835 | } | ||||
| 2836 | } | ||||
| 2837 | |||||
| 2838 | // verifyBasicBlock - Verify that a basic block is well formed... | ||||
| 2839 | // | ||||
| 2840 | void Verifier::visitBasicBlock(BasicBlock &BB) { | ||||
| 2841 | InstsInThisBlock.clear(); | ||||
| 2842 | |||||
| 2843 | // Ensure that basic blocks have terminators! | ||||
| 2844 | Check(BB.getTerminator(), "Basic Block does not have terminator!", &BB)do { if (!(BB.getTerminator())) { CheckFailed("Basic Block does not have terminator!" , &BB); return; } } while (false); | ||||
| 2845 | |||||
| 2846 | // Check constraints that this basic block imposes on all of the PHI nodes in | ||||
| 2847 | // it. | ||||
| 2848 | if (isa<PHINode>(BB.front())) { | ||||
| 2849 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||
| 2850 | SmallVector<std::pair<BasicBlock*, Value*>, 8> Values; | ||||
| 2851 | llvm::sort(Preds); | ||||
| 2852 | for (const PHINode &PN : BB.phis()) { | ||||
| 2853 | Check(PN.getNumIncomingValues() == Preds.size(),do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2854 | "PHINode should have one entry for each predecessor of its "do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2855 | "parent basic block!",do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false) | ||||
| 2856 | &PN)do { if (!(PN.getNumIncomingValues() == Preds.size())) { CheckFailed ("PHINode should have one entry for each predecessor of its " "parent basic block!", &PN); return; } } while (false); | ||||
| 2857 | |||||
| 2858 | // Get and sort all incoming values in the PHI node... | ||||
| 2859 | Values.clear(); | ||||
| 2860 | Values.reserve(PN.getNumIncomingValues()); | ||||
| 2861 | for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) | ||||
| 2862 | Values.push_back( | ||||
| 2863 | std::make_pair(PN.getIncomingBlock(i), PN.getIncomingValue(i))); | ||||
| 2864 | llvm::sort(Values); | ||||
| 2865 | |||||
| 2866 | for (unsigned i = 0, e = Values.size(); i != e; ++i) { | ||||
| 2867 | // Check to make sure that if there is more than one entry for a | ||||
| 2868 | // particular basic block in this PHI node, that the incoming values are | ||||
| 2869 | // all identical. | ||||
| 2870 | // | ||||
| 2871 | Check(i == 0 || Values[i].first != Values[i - 1].first ||do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2872 | Values[i].second == Values[i - 1].second,do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2873 | "PHI node has multiple entries for the same basic block with "do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2874 | "different incoming values!",do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false) | ||||
| 2875 | &PN, Values[i].first, Values[i].second, Values[i - 1].second)do { if (!(i == 0 || Values[i].first != Values[i - 1].first || Values[i].second == Values[i - 1].second)) { CheckFailed("PHI node has multiple entries for the same basic block with " "different incoming values!", &PN, Values[i].first, Values [i].second, Values[i - 1].second); return; } } while (false); | ||||
| 2876 | |||||
| 2877 | // Check to make sure that the predecessors and PHI node entries are | ||||
| 2878 | // matched up. | ||||
| 2879 | Check(Values[i].first == Preds[i],do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
| 2880 | "PHI node entries do not match predecessors!", &PN,do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ) | ||||
| 2881 | Values[i].first, Preds[i])do { if (!(Values[i].first == Preds[i])) { CheckFailed("PHI node entries do not match predecessors!" , &PN, Values[i].first, Preds[i]); return; } } while (false ); | ||||
| 2882 | } | ||||
| 2883 | } | ||||
| 2884 | } | ||||
| 2885 | |||||
| 2886 | // Check that all instructions have their parent pointers set up correctly. | ||||
| 2887 | for (auto &I : BB) | ||||
| 2888 | { | ||||
| 2889 | Check(I.getParent() == &BB, "Instruction has bogus parent pointer!")do { if (!(I.getParent() == &BB)) { CheckFailed("Instruction has bogus parent pointer!" ); return; } } while (false); | ||||
| 2890 | } | ||||
| 2891 | } | ||||
| 2892 | |||||
| 2893 | void Verifier::visitTerminator(Instruction &I) { | ||||
| 2894 | // Ensure that terminators only exist at the end of the basic block. | ||||
| 2895 | Check(&I == I.getParent()->getTerminator(),do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false) | ||||
| 2896 | "Terminator found in the middle of a basic block!", I.getParent())do { if (!(&I == I.getParent()->getTerminator())) { CheckFailed ("Terminator found in the middle of a basic block!", I.getParent ()); return; } } while (false); | ||||
| 2897 | visitInstruction(I); | ||||
| 2898 | } | ||||
| 2899 | |||||
| 2900 | void Verifier::visitBranchInst(BranchInst &BI) { | ||||
| 2901 | if (BI.isConditional()) { | ||||
| 2902 | Check(BI.getCondition()->getType()->isIntegerTy(1),do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false) | ||||
| 2903 | "Branch condition is not 'i1' type!", &BI, BI.getCondition())do { if (!(BI.getCondition()->getType()->isIntegerTy(1) )) { CheckFailed("Branch condition is not 'i1' type!", &BI , BI.getCondition()); return; } } while (false); | ||||
| 2904 | } | ||||
| 2905 | visitTerminator(BI); | ||||
| 2906 | } | ||||
| 2907 | |||||
| 2908 | void Verifier::visitReturnInst(ReturnInst &RI) { | ||||
| 2909 | Function *F = RI.getParent()->getParent(); | ||||
| 2910 | unsigned N = RI.getNumOperands(); | ||||
| 2911 | if (F->getReturnType()->isVoidTy()) | ||||
| 2912 | Check(N == 0,do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2913 | "Found return instr that returns non-void in Function of void "do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2914 | "return type!",do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false) | ||||
| 2915 | &RI, F->getReturnType())do { if (!(N == 0)) { CheckFailed("Found return instr that returns non-void in Function of void " "return type!", &RI, F->getReturnType()); return; } } while (false); | ||||
| 2916 | else | ||||
| 2917 | Check(N == 1 && F->getReturnType() == RI.getOperand(0)->getType(),do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2918 | "Function return type does not match operand "do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2919 | "type of return inst!",do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false) | ||||
| 2920 | &RI, F->getReturnType())do { if (!(N == 1 && F->getReturnType() == RI.getOperand (0)->getType())) { CheckFailed("Function return type does not match operand " "type of return inst!", &RI, F->getReturnType()); return ; } } while (false); | ||||
| 2921 | |||||
| 2922 | // Check to make sure that the return value has necessary properties for | ||||
| 2923 | // terminators... | ||||
| 2924 | visitTerminator(RI); | ||||
| 2925 | } | ||||
| 2926 | |||||
| 2927 | void Verifier::visitSwitchInst(SwitchInst &SI) { | ||||
| 2928 | Check(SI.getType()->isVoidTy(), "Switch must have void result type!", &SI)do { if (!(SI.getType()->isVoidTy())) { CheckFailed("Switch must have void result type!" , &SI); return; } } while (false); | ||||
| 2929 | // Check to make sure that all of the constants in the switch instruction | ||||
| 2930 | // have the same type as the switched-on value. | ||||
| 2931 | Type *SwitchTy = SI.getCondition()->getType(); | ||||
| 2932 | SmallPtrSet<ConstantInt*, 32> Constants; | ||||
| 2933 | for (auto &Case : SI.cases()) { | ||||
| 2934 | Check(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex() * 2 + 2)),do { if (!(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex () * 2 + 2)))) { CheckFailed("Case value is not a constant integer." , &SI); return; } } while (false) | ||||
| 2935 | "Case value is not a constant integer.", &SI)do { if (!(isa<ConstantInt>(SI.getOperand(Case.getCaseIndex () * 2 + 2)))) { CheckFailed("Case value is not a constant integer." , &SI); return; } } while (false); | ||||
| 2936 | Check(Case.getCaseValue()->getType() == SwitchTy,do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false) | ||||
| 2937 | "Switch constants must all be same type as switch value!", &SI)do { if (!(Case.getCaseValue()->getType() == SwitchTy)) { CheckFailed ("Switch constants must all be same type as switch value!", & SI); return; } } while (false); | ||||
| 2938 | Check(Constants.insert(Case.getCaseValue()).second,do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false) | ||||
| 2939 | "Duplicate integer as switch case", &SI, Case.getCaseValue())do { if (!(Constants.insert(Case.getCaseValue()).second)) { CheckFailed ("Duplicate integer as switch case", &SI, Case.getCaseValue ()); return; } } while (false); | ||||
| 2940 | } | ||||
| 2941 | |||||
| 2942 | visitTerminator(SI); | ||||
| 2943 | } | ||||
| 2944 | |||||
| 2945 | void Verifier::visitIndirectBrInst(IndirectBrInst &BI) { | ||||
| 2946 | Check(BI.getAddress()->getType()->isPointerTy(),do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false) | ||||
| 2947 | "Indirectbr operand must have pointer type!", &BI)do { if (!(BI.getAddress()->getType()->isPointerTy())) { CheckFailed("Indirectbr operand must have pointer type!", & BI); return; } } while (false); | ||||
| 2948 | for (unsigned i = 0, e = BI.getNumDestinations(); i != e; ++i) | ||||
| 2949 | Check(BI.getDestination(i)->getType()->isLabelTy(),do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false) | ||||
| 2950 | "Indirectbr destinations must all have pointer type!", &BI)do { if (!(BI.getDestination(i)->getType()->isLabelTy() )) { CheckFailed("Indirectbr destinations must all have pointer type!" , &BI); return; } } while (false); | ||||
| 2951 | |||||
| 2952 | visitTerminator(BI); | ||||
| 2953 | } | ||||
| 2954 | |||||
| 2955 | void Verifier::visitCallBrInst(CallBrInst &CBI) { | ||||
| 2956 | Check(CBI.isInlineAsm(), "Callbr is currently only used for asm-goto!", &CBI)do { if (!(CBI.isInlineAsm())) { CheckFailed("Callbr is currently only used for asm-goto!" , &CBI); return; } } while (false); | ||||
| 2957 | const InlineAsm *IA = cast<InlineAsm>(CBI.getCalledOperand()); | ||||
| 2958 | Check(!IA->canThrow(), "Unwinding from Callbr is not allowed")do { if (!(!IA->canThrow())) { CheckFailed("Unwinding from Callbr is not allowed" ); return; } } while (false); | ||||
| 2959 | |||||
| 2960 | verifyInlineAsmCall(CBI); | ||||
| 2961 | visitTerminator(CBI); | ||||
| 2962 | } | ||||
| 2963 | |||||
| 2964 | void Verifier::visitSelectInst(SelectInst &SI) { | ||||
| 2965 | Check(!SelectInst::areInvalidOperands(SI.getOperand(0), SI.getOperand(1),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
| 2966 | SI.getOperand(2)),do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false) | ||||
| 2967 | "Invalid operands for select instruction!", &SI)do { if (!(!SelectInst::areInvalidOperands(SI.getOperand(0), SI .getOperand(1), SI.getOperand(2)))) { CheckFailed("Invalid operands for select instruction!" , &SI); return; } } while (false); | ||||
| 2968 | |||||
| 2969 | Check(SI.getTrueValue()->getType() == SI.getType(),do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false) | ||||
| 2970 | "Select values must have same type as select instruction!", &SI)do { if (!(SI.getTrueValue()->getType() == SI.getType())) { CheckFailed("Select values must have same type as select instruction!" , &SI); return; } } while (false); | ||||
| 2971 | visitInstruction(SI); | ||||
| 2972 | } | ||||
| 2973 | |||||
| 2974 | /// visitUserOp1 - User defined operators shouldn't live beyond the lifetime of | ||||
| 2975 | /// a pass, if any exist, it's an error. | ||||
| 2976 | /// | ||||
| 2977 | void Verifier::visitUserOp1(Instruction &I) { | ||||
| 2978 | Check(false, "User-defined operators should not live outside of a pass!", &I)do { if (!(false)) { CheckFailed("User-defined operators should not live outside of a pass!" , &I); return; } } while (false); | ||||
| 2979 | } | ||||
| 2980 | |||||
| 2981 | void Verifier::visitTruncInst(TruncInst &I) { | ||||
| 2982 | // Get the source and destination types | ||||
| 2983 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 2984 | Type *DestTy = I.getType(); | ||||
| 2985 | |||||
| 2986 | // Get the size of the types in bits, we'll need this later | ||||
| 2987 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 2988 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 2989 | |||||
| 2990 | Check(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only operates on integer" , &I); return; } } while (false); | ||||
| 2991 | Check(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("Trunc only produces integer" , &I); return; } } while (false); | ||||
| 2992 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 2993 | "trunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("trunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 2994 | Check(SrcBitSize > DestBitSize, "DestTy too big for Trunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for Trunc" , &I); return; } } while (false); | ||||
| 2995 | |||||
| 2996 | visitInstruction(I); | ||||
| 2997 | } | ||||
| 2998 | |||||
| 2999 | void Verifier::visitZExtInst(ZExtInst &I) { | ||||
| 3000 | // Get the source and destination types | ||||
| 3001 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3002 | Type *DestTy = I.getType(); | ||||
| 3003 | |||||
| 3004 | // Get the size of the types in bits, we'll need this later | ||||
| 3005 | Check(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only operates on integer" , &I); return; } } while (false); | ||||
| 3006 | Check(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("ZExt only produces an integer" , &I); return; } } while (false); | ||||
| 3007 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 3008 | "zext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("zext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 3009 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 3010 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 3011 | |||||
| 3012 | Check(SrcBitSize < DestBitSize, "Type too small for ZExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for ZExt" , &I); return; } } while (false); | ||||
| 3013 | |||||
| 3014 | visitInstruction(I); | ||||
| 3015 | } | ||||
| 3016 | |||||
| 3017 | void Verifier::visitSExtInst(SExtInst &I) { | ||||
| 3018 | // Get the source and destination types | ||||
| 3019 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3020 | Type *DestTy = I.getType(); | ||||
| 3021 | |||||
| 3022 | // Get the size of the types in bits, we'll need this later | ||||
| 3023 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 3024 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 3025 | |||||
| 3026 | Check(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SExt only operates on integer" , &I); return; } } while (false); | ||||
| 3027 | Check(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("SExt only produces an integer" , &I); return; } } while (false); | ||||
| 3028 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 3029 | "sext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("sext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 3030 | Check(SrcBitSize < DestBitSize, "Type too small for SExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("Type too small for SExt" , &I); return; } } while (false); | ||||
| 3031 | |||||
| 3032 | visitInstruction(I); | ||||
| 3033 | } | ||||
| 3034 | |||||
| 3035 | void Verifier::visitFPTruncInst(FPTruncInst &I) { | ||||
| 3036 | // Get the source and destination types | ||||
| 3037 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3038 | Type *DestTy = I.getType(); | ||||
| 3039 | // Get the size of the types in bits, we'll need this later | ||||
| 3040 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 3041 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 3042 | |||||
| 3043 | Check(SrcTy->isFPOrFPVectorTy(), "FPTrunc only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only operates on FP" , &I); return; } } while (false); | ||||
| 3044 | Check(DestTy->isFPOrFPVectorTy(), "FPTrunc only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPTrunc only produces an FP" , &I); return; } } while (false); | ||||
| 3045 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 3046 | "fptrunc source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fptrunc source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 3047 | Check(SrcBitSize > DestBitSize, "DestTy too big for FPTrunc", &I)do { if (!(SrcBitSize > DestBitSize)) { CheckFailed("DestTy too big for FPTrunc" , &I); return; } } while (false); | ||||
| 3048 | |||||
| 3049 | visitInstruction(I); | ||||
| 3050 | } | ||||
| 3051 | |||||
| 3052 | void Verifier::visitFPExtInst(FPExtInst &I) { | ||||
| 3053 | // Get the source and destination types | ||||
| 3054 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3055 | Type *DestTy = I.getType(); | ||||
| 3056 | |||||
| 3057 | // Get the size of the types in bits, we'll need this later | ||||
| 3058 | unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); | ||||
| 3059 | unsigned DestBitSize = DestTy->getScalarSizeInBits(); | ||||
| 3060 | |||||
| 3061 | Check(SrcTy->isFPOrFPVectorTy(), "FPExt only operates on FP", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only operates on FP" , &I); return; } } while (false); | ||||
| 3062 | Check(DestTy->isFPOrFPVectorTy(), "FPExt only produces an FP", &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("FPExt only produces an FP" , &I); return; } } while (false); | ||||
| 3063 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(),do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false) | ||||
| 3064 | "fpext source and destination must both be a vector or neither", &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("fpext source and destination must both be a vector or neither" , &I); return; } } while (false); | ||||
| 3065 | Check(SrcBitSize < DestBitSize, "DestTy too small for FPExt", &I)do { if (!(SrcBitSize < DestBitSize)) { CheckFailed("DestTy too small for FPExt" , &I); return; } } while (false); | ||||
| 3066 | |||||
| 3067 | visitInstruction(I); | ||||
| 3068 | } | ||||
| 3069 | |||||
| 3070 | void Verifier::visitUIToFPInst(UIToFPInst &I) { | ||||
| 3071 | // Get the source and destination types | ||||
| 3072 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3073 | Type *DestTy = I.getType(); | ||||
| 3074 | |||||
| 3075 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 3076 | bool DstVec = DestTy->isVectorTy(); | ||||
| 3077 | |||||
| 3078 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 3079 | "UIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("UIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 3080 | Check(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
| 3081 | "UIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("UIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
| 3082 | Check(DestTy->isFPOrFPVectorTy(), "UIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
| 3083 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("UIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
| 3084 | |||||
| 3085 | if (SrcVec && DstVec) | ||||
| 3086 | Check(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3087 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3088 | "UIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("UIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 3089 | |||||
| 3090 | visitInstruction(I); | ||||
| 3091 | } | ||||
| 3092 | |||||
| 3093 | void Verifier::visitSIToFPInst(SIToFPInst &I) { | ||||
| 3094 | // Get the source and destination types | ||||
| 3095 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3096 | Type *DestTy = I.getType(); | ||||
| 3097 | |||||
| 3098 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 3099 | bool DstVec = DestTy->isVectorTy(); | ||||
| 3100 | |||||
| 3101 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 3102 | "SIToFP source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("SIToFP source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 3103 | Check(SrcTy->isIntOrIntVectorTy(),do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false) | ||||
| 3104 | "SIToFP source must be integer or integer vector", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("SIToFP source must be integer or integer vector" , &I); return; } } while (false); | ||||
| 3105 | Check(DestTy->isFPOrFPVectorTy(), "SIToFP result must be FP or FP vector",do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false) | ||||
| 3106 | &I)do { if (!(DestTy->isFPOrFPVectorTy())) { CheckFailed("SIToFP result must be FP or FP vector" , &I); return; } } while (false); | ||||
| 3107 | |||||
| 3108 | if (SrcVec && DstVec) | ||||
| 3109 | Check(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3110 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3111 | "SIToFP source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("SIToFP source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 3112 | |||||
| 3113 | visitInstruction(I); | ||||
| 3114 | } | ||||
| 3115 | |||||
| 3116 | void Verifier::visitFPToUIInst(FPToUIInst &I) { | ||||
| 3117 | // Get the source and destination types | ||||
| 3118 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3119 | Type *DestTy = I.getType(); | ||||
| 3120 | |||||
| 3121 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 3122 | bool DstVec = DestTy->isVectorTy(); | ||||
| 3123 | |||||
| 3124 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 3125 | "FPToUI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToUI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 3126 | Check(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToUI source must be FP or FP vector" , &I); return; } } while (false); | ||||
| 3127 | Check(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false) | ||||
| 3128 | "FPToUI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToUI result must be integer or integer vector" , &I); return; } } while (false); | ||||
| 3129 | |||||
| 3130 | if (SrcVec && DstVec) | ||||
| 3131 | Check(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3132 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3133 | "FPToUI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToUI source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 3134 | |||||
| 3135 | visitInstruction(I); | ||||
| 3136 | } | ||||
| 3137 | |||||
| 3138 | void Verifier::visitFPToSIInst(FPToSIInst &I) { | ||||
| 3139 | // Get the source and destination types | ||||
| 3140 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3141 | Type *DestTy = I.getType(); | ||||
| 3142 | |||||
| 3143 | bool SrcVec = SrcTy->isVectorTy(); | ||||
| 3144 | bool DstVec = DestTy->isVectorTy(); | ||||
| 3145 | |||||
| 3146 | Check(SrcVec == DstVec,do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false) | ||||
| 3147 | "FPToSI source and dest must both be vector or scalar", &I)do { if (!(SrcVec == DstVec)) { CheckFailed("FPToSI source and dest must both be vector or scalar" , &I); return; } } while (false); | ||||
| 3148 | Check(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector", &I)do { if (!(SrcTy->isFPOrFPVectorTy())) { CheckFailed("FPToSI source must be FP or FP vector" , &I); return; } } while (false); | ||||
| 3149 | Check(DestTy->isIntOrIntVectorTy(),do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false) | ||||
| 3150 | "FPToSI result must be integer or integer vector", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("FPToSI result must be integer or integer vector" , &I); return; } } while (false); | ||||
| 3151 | |||||
| 3152 | if (SrcVec && DstVec) | ||||
| 3153 | Check(cast<VectorType>(SrcTy)->getElementCount() ==do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3154 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false) | ||||
| 3155 | "FPToSI source and dest vector length mismatch", &I)do { if (!(cast<VectorType>(SrcTy)->getElementCount( ) == cast<VectorType>(DestTy)->getElementCount())) { CheckFailed("FPToSI source and dest vector length mismatch", &I); return; } } while (false); | ||||
| 3156 | |||||
| 3157 | visitInstruction(I); | ||||
| 3158 | } | ||||
| 3159 | |||||
| 3160 | void Verifier::visitPtrToIntInst(PtrToIntInst &I) { | ||||
| 3161 | // Get the source and destination types | ||||
| 3162 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3163 | Type *DestTy = I.getType(); | ||||
| 3164 | |||||
| 3165 | Check(SrcTy->isPtrOrPtrVectorTy(), "PtrToInt source must be pointer", &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("PtrToInt source must be pointer" , &I); return; } } while (false); | ||||
| 3166 | |||||
| 3167 | Check(DestTy->isIntOrIntVectorTy(), "PtrToInt result must be integral", &I)do { if (!(DestTy->isIntOrIntVectorTy())) { CheckFailed("PtrToInt result must be integral" , &I); return; } } while (false); | ||||
| 3168 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToInt type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false) | ||||
| 3169 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("PtrToInt type mismatch", &I); return; } } while (false); | ||||
| 3170 | |||||
| 3171 | if (SrcTy->isVectorTy()) { | ||||
| 3172 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
| 3173 | auto *VDest = cast<VectorType>(DestTy); | ||||
| 3174 | Check(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false) | ||||
| 3175 | "PtrToInt Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("PtrToInt Vector width mismatch", &I); return; } } while (false); | ||||
| 3176 | } | ||||
| 3177 | |||||
| 3178 | visitInstruction(I); | ||||
| 3179 | } | ||||
| 3180 | |||||
| 3181 | void Verifier::visitIntToPtrInst(IntToPtrInst &I) { | ||||
| 3182 | // Get the source and destination types | ||||
| 3183 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3184 | Type *DestTy = I.getType(); | ||||
| 3185 | |||||
| 3186 | Check(SrcTy->isIntOrIntVectorTy(), "IntToPtr source must be an integral", &I)do { if (!(SrcTy->isIntOrIntVectorTy())) { CheckFailed("IntToPtr source must be an integral" , &I); return; } } while (false); | ||||
| 3187 | Check(DestTy->isPtrOrPtrVectorTy(), "IntToPtr result must be a pointer", &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("IntToPtr result must be a pointer" , &I); return; } } while (false); | ||||
| 3188 | |||||
| 3189 | Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "IntToPtr type mismatch",do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false) | ||||
| 3190 | &I)do { if (!(SrcTy->isVectorTy() == DestTy->isVectorTy()) ) { CheckFailed("IntToPtr type mismatch", &I); return; } } while (false); | ||||
| 3191 | if (SrcTy->isVectorTy()) { | ||||
| 3192 | auto *VSrc = cast<VectorType>(SrcTy); | ||||
| 3193 | auto *VDest = cast<VectorType>(DestTy); | ||||
| 3194 | Check(VSrc->getElementCount() == VDest->getElementCount(),do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false) | ||||
| 3195 | "IntToPtr Vector width mismatch", &I)do { if (!(VSrc->getElementCount() == VDest->getElementCount ())) { CheckFailed("IntToPtr Vector width mismatch", &I); return; } } while (false); | ||||
| 3196 | } | ||||
| 3197 | visitInstruction(I); | ||||
| 3198 | } | ||||
| 3199 | |||||
| 3200 | void Verifier::visitBitCastInst(BitCastInst &I) { | ||||
| 3201 | Check(do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
| 3202 | CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()),do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false) | ||||
| 3203 | "Invalid bitcast", &I)do { if (!(CastInst::castIsValid(Instruction::BitCast, I.getOperand (0), I.getType()))) { CheckFailed("Invalid bitcast", &I); return; } } while (false); | ||||
| 3204 | visitInstruction(I); | ||||
| 3205 | } | ||||
| 3206 | |||||
| 3207 | void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) { | ||||
| 3208 | Type *SrcTy = I.getOperand(0)->getType(); | ||||
| 3209 | Type *DestTy = I.getType(); | ||||
| 3210 | |||||
| 3211 | Check(SrcTy->isPtrOrPtrVectorTy(), "AddrSpaceCast source must be a pointer",do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false) | ||||
| 3212 | &I)do { if (!(SrcTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast source must be a pointer" , &I); return; } } while (false); | ||||
| 3213 | Check(DestTy->isPtrOrPtrVectorTy(), "AddrSpaceCast result must be a pointer",do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false) | ||||
| 3214 | &I)do { if (!(DestTy->isPtrOrPtrVectorTy())) { CheckFailed("AddrSpaceCast result must be a pointer" , &I); return; } } while (false); | ||||
| 3215 | Check(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false) | ||||
| 3216 | "AddrSpaceCast must be between different address spaces", &I)do { if (!(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace ())) { CheckFailed("AddrSpaceCast must be between different address spaces" , &I); return; } } while (false); | ||||
| 3217 | if (auto *SrcVTy = dyn_cast<VectorType>(SrcTy)) | ||||
| 3218 | Check(SrcVTy->getElementCount() ==do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
| 3219 | cast<VectorType>(DestTy)->getElementCount(),do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false) | ||||
| 3220 | "AddrSpaceCast vector pointer number of elements mismatch", &I)do { if (!(SrcVTy->getElementCount() == cast<VectorType >(DestTy)->getElementCount())) { CheckFailed("AddrSpaceCast vector pointer number of elements mismatch" , &I); return; } } while (false); | ||||
| 3221 | visitInstruction(I); | ||||
| 3222 | } | ||||
| 3223 | |||||
| 3224 | /// visitPHINode - Ensure that a PHI node is well formed. | ||||
| 3225 | /// | ||||
| 3226 | void Verifier::visitPHINode(PHINode &PN) { | ||||
| 3227 | // Ensure that the PHI nodes are all grouped together at the top of the block. | ||||
| 3228 | // This can be tested by checking whether the instruction before this is | ||||
| 3229 | // either nonexistent (because this is begin()) or is a PHI node. If not, | ||||
| 3230 | // then there is some other instruction before a PHI. | ||||
| 3231 | Check(&PN == &PN.getParent()->front() ||do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
| 3232 | isa<PHINode>(--BasicBlock::iterator(&PN)),do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false) | ||||
| 3233 | "PHI nodes not grouped at top of basic block!", &PN, PN.getParent())do { if (!(&PN == &PN.getParent()->front() || isa< PHINode>(--BasicBlock::iterator(&PN)))) { CheckFailed( "PHI nodes not grouped at top of basic block!", &PN, PN.getParent ()); return; } } while (false); | ||||
| 3234 | |||||
| 3235 | // Check that a PHI doesn't yield a Token. | ||||
| 3236 | Check(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!")do { if (!(!PN.getType()->isTokenTy())) { CheckFailed("PHI nodes cannot have token type!" ); return; } } while (false); | ||||
| 3237 | |||||
| 3238 | // Check that all of the values of the PHI node have the same type as the | ||||
| 3239 | // result, and that the incoming blocks are really basic blocks. | ||||
| 3240 | for (Value *IncValue : PN.incoming_values()) { | ||||
| 3241 | Check(PN.getType() == IncValue->getType(),do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false) | ||||
| 3242 | "PHI node operands are not the same type as the result!", &PN)do { if (!(PN.getType() == IncValue->getType())) { CheckFailed ("PHI node operands are not the same type as the result!", & PN); return; } } while (false); | ||||
| 3243 | } | ||||
| 3244 | |||||
| 3245 | // All other PHI node constraints are checked in the visitBasicBlock method. | ||||
| 3246 | |||||
| 3247 | visitInstruction(PN); | ||||
| 3248 | } | ||||
| 3249 | |||||
| 3250 | void Verifier::visitCallBase(CallBase &Call) { | ||||
| 3251 | Check(Call.getCalledOperand()->getType()->isPointerTy(),do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false) | ||||
| 3252 | "Called function must be a pointer!", Call)do { if (!(Call.getCalledOperand()->getType()->isPointerTy ())) { CheckFailed("Called function must be a pointer!", Call ); return; } } while (false); | ||||
| 3253 | PointerType *FPTy = cast<PointerType>(Call.getCalledOperand()->getType()); | ||||
| 3254 | |||||
| 3255 | Check(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType()),do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false) | ||||
| 3256 | "Called function is not the same type as the call!", Call)do { if (!(FPTy->isOpaqueOrPointeeTypeMatches(Call.getFunctionType ()))) { CheckFailed("Called function is not the same type as the call!" , Call); return; } } while (false); | ||||
| 3257 | |||||
| 3258 | FunctionType *FTy = Call.getFunctionType(); | ||||
| 3259 | |||||
| 3260 | // Verify that the correct number of arguments are being passed | ||||
| 3261 | if (FTy->isVarArg()) | ||||
| 3262 | Check(Call.arg_size() >= FTy->getNumParams(),do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false) | ||||
| 3263 | "Called function requires more parameters than were provided!", Call)do { if (!(Call.arg_size() >= FTy->getNumParams())) { CheckFailed ("Called function requires more parameters than were provided!" , Call); return; } } while (false); | ||||
| 3264 | else | ||||
| 3265 | Check(Call.arg_size() == FTy->getNumParams(),do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false) | ||||
| 3266 | "Incorrect number of arguments passed to called function!", Call)do { if (!(Call.arg_size() == FTy->getNumParams())) { CheckFailed ("Incorrect number of arguments passed to called function!", Call ); return; } } while (false); | ||||
| 3267 | |||||
| 3268 | // Verify that all arguments to the call match the function type. | ||||
| 3269 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) | ||||
| 3270 | Check(Call.getArgOperand(i)->getType() == FTy->getParamType(i),do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
| 3271 | "Call parameter type does not match function signature!",do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false) | ||||
| 3272 | Call.getArgOperand(i), FTy->getParamType(i), Call)do { if (!(Call.getArgOperand(i)->getType() == FTy->getParamType (i))) { CheckFailed("Call parameter type does not match function signature!" , Call.getArgOperand(i), FTy->getParamType(i), Call); return ; } } while (false); | ||||
| 3273 | |||||
| 3274 | AttributeList Attrs = Call.getAttributes(); | ||||
| 3275 | |||||
| 3276 | Check(verifyAttributeCount(Attrs, Call.arg_size()),do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false) | ||||
| 3277 | "Attribute after last parameter!", Call)do { if (!(verifyAttributeCount(Attrs, Call.arg_size()))) { CheckFailed ("Attribute after last parameter!", Call); return; } } while ( false); | ||||
| 3278 | |||||
| 3279 | Function *Callee = | ||||
| 3280 | dyn_cast<Function>(Call.getCalledOperand()->stripPointerCasts()); | ||||
| 3281 | bool IsIntrinsic = Callee && Callee->isIntrinsic(); | ||||
| 3282 | if (IsIntrinsic) | ||||
| 3283 | Check(Callee->getValueType() == FTy,do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false) | ||||
| 3284 | "Intrinsic called with incompatible signature", Call)do { if (!(Callee->getValueType() == FTy)) { CheckFailed("Intrinsic called with incompatible signature" , Call); return; } } while (false); | ||||
| 3285 | |||||
| 3286 | auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) { | ||||
| 3287 | if (!Ty->isSized()) | ||||
| 3288 | return; | ||||
| 3289 | Align ABIAlign = DL.getABITypeAlign(Ty); | ||||
| 3290 | Align MaxAlign(ParamMaxAlignment); | ||||
| 3291 | Check(ABIAlign <= MaxAlign,do { if (!(ABIAlign <= MaxAlign)) { CheckFailed("Incorrect alignment of " + Message + " to called function!", Call); return; } } while (false) | ||||
| 3292 | "Incorrect alignment of " + Message + " to called function!", Call)do { if (!(ABIAlign <= MaxAlign)) { CheckFailed("Incorrect alignment of " + Message + " to called function!", Call); return; } } while (false); | ||||
| 3293 | }; | ||||
| 3294 | |||||
| 3295 | if (!IsIntrinsic) { | ||||
| 3296 | VerifyTypeAlign(FTy->getReturnType(), "return type"); | ||||
| 3297 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
| 3298 | Type *Ty = FTy->getParamType(i); | ||||
| 3299 | VerifyTypeAlign(Ty, "argument passed"); | ||||
| 3300 | } | ||||
| 3301 | } | ||||
| 3302 | |||||
| 3303 | if (Attrs.hasFnAttr(Attribute::Speculatable)) { | ||||
| 3304 | // Don't allow speculatable on call sites, unless the underlying function | ||||
| 3305 | // declaration is also speculatable. | ||||
| 3306 | Check(Callee && Callee->isSpeculatable(),do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false) | ||||
| 3307 | "speculatable attribute may not apply to call sites", Call)do { if (!(Callee && Callee->isSpeculatable())) { CheckFailed ("speculatable attribute may not apply to call sites", Call); return; } } while (false); | ||||
| 3308 | } | ||||
| 3309 | |||||
| 3310 | if (Attrs.hasFnAttr(Attribute::Preallocated)) { | ||||
| 3311 | Check(Call.getCalledFunction()->getIntrinsicID() ==do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3312 | Intrinsic::call_preallocated_arg,do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3313 | "preallocated as a call site attribute can only be on "do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false) | ||||
| 3314 | "llvm.call.preallocated.arg")do { if (!(Call.getCalledFunction()->getIntrinsicID() == Intrinsic ::call_preallocated_arg)) { CheckFailed("preallocated as a call site attribute can only be on " "llvm.call.preallocated.arg"); return; } } while (false); | ||||
| 3315 | } | ||||
| 3316 | |||||
| 3317 | // Verify call attributes. | ||||
| 3318 | verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic, Call.isInlineAsm()); | ||||
| 3319 | |||||
| 3320 | // Conservatively check the inalloca argument. | ||||
| 3321 | // We have a bug if we can find that there is an underlying alloca without | ||||
| 3322 | // inalloca. | ||||
| 3323 | if (Call.hasInAllocaArgument()) { | ||||
| 3324 | Value *InAllocaArg = Call.getArgOperand(FTy->getNumParams() - 1); | ||||
| 3325 | if (auto AI = dyn_cast<AllocaInst>(InAllocaArg->stripInBoundsOffsets())) | ||||
| 3326 | Check(AI->isUsedWithInAlloca(),do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
| 3327 | "inalloca argument for call has mismatched alloca", AI, Call)do { if (!(AI->isUsedWithInAlloca())) { CheckFailed("inalloca argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
| 3328 | } | ||||
| 3329 | |||||
| 3330 | // For each argument of the callsite, if it has the swifterror argument, | ||||
| 3331 | // make sure the underlying alloca/parameter it comes from has a swifterror as | ||||
| 3332 | // well. | ||||
| 3333 | for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) { | ||||
| 3334 | if (Call.paramHasAttr(i, Attribute::SwiftError)) { | ||||
| 3335 | Value *SwiftErrorArg = Call.getArgOperand(i); | ||||
| 3336 | if (auto AI = dyn_cast<AllocaInst>(SwiftErrorArg->stripInBoundsOffsets())) { | ||||
| 3337 | Check(AI->isSwiftError(),do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false) | ||||
| 3338 | "swifterror argument for call has mismatched alloca", AI, Call)do { if (!(AI->isSwiftError())) { CheckFailed("swifterror argument for call has mismatched alloca" , AI, Call); return; } } while (false); | ||||
| 3339 | continue; | ||||
| 3340 | } | ||||
| 3341 | auto ArgI = dyn_cast<Argument>(SwiftErrorArg); | ||||
| 3342 | Check(ArgI, "swifterror argument should come from an alloca or parameter",do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false) | ||||
| 3343 | SwiftErrorArg, Call)do { if (!(ArgI)) { CheckFailed("swifterror argument should come from an alloca or parameter" , SwiftErrorArg, Call); return; } } while (false); | ||||
| 3344 | Check(ArgI->hasSwiftErrorAttr(),do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
| 3345 | "swifterror argument for call has mismatched parameter", ArgI,do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false) | ||||
| 3346 | Call)do { if (!(ArgI->hasSwiftErrorAttr())) { CheckFailed("swifterror argument for call has mismatched parameter" , ArgI, Call); return; } } while (false); | ||||
| 3347 | } | ||||
| 3348 | |||||
| 3349 | if (Attrs.hasParamAttr(i, Attribute::ImmArg)) { | ||||
| 3350 | // Don't allow immarg on call sites, unless the underlying declaration | ||||
| 3351 | // also has the matching immarg. | ||||
| 3352 | Check(Callee && Callee->hasParamAttribute(i, Attribute::ImmArg),do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
| 3353 | "immarg may not apply only to call sites", Call.getArgOperand(i),do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false) | ||||
| 3354 | Call)do { if (!(Callee && Callee->hasParamAttribute(i, Attribute ::ImmArg))) { CheckFailed("immarg may not apply only to call sites" , Call.getArgOperand(i), Call); return; } } while (false); | ||||
| 3355 | } | ||||
| 3356 | |||||
| 3357 | if (Call.paramHasAttr(i, Attribute::ImmArg)) { | ||||
| 3358 | Value *ArgVal = Call.getArgOperand(i); | ||||
| 3359 | Check(isa<ConstantInt>(ArgVal) || isa<ConstantFP>(ArgVal),do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false) | ||||
| 3360 | "immarg operand has non-immediate parameter", ArgVal, Call)do { if (!(isa<ConstantInt>(ArgVal) || isa<ConstantFP >(ArgVal))) { CheckFailed("immarg operand has non-immediate parameter" , ArgVal, Call); return; } } while (false); | ||||
| 3361 | } | ||||
| 3362 | |||||
| 3363 | if (Call.paramHasAttr(i, Attribute::Preallocated)) { | ||||
| 3364 | Value *ArgVal = Call.getArgOperand(i); | ||||
| 3365 | bool hasOB = | ||||
| 3366 | Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; | ||||
| 3367 | bool isMustTail = Call.isMustTailCall(); | ||||
| 3368 | Check(hasOB != isMustTail,do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3369 | "preallocated operand either requires a preallocated bundle or "do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3370 | "the call to be musttail (but not both)",do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false) | ||||
| 3371 | ArgVal, Call)do { if (!(hasOB != isMustTail)) { CheckFailed("preallocated operand either requires a preallocated bundle or " "the call to be musttail (but not both)", ArgVal, Call); return ; } } while (false); | ||||
| 3372 | } | ||||
| 3373 | } | ||||
| 3374 | |||||
| 3375 | if (FTy->isVarArg()) { | ||||
| 3376 | // FIXME? is 'nest' even legal here? | ||||
| 3377 | bool SawNest = false; | ||||
| 3378 | bool SawReturned = false; | ||||
| 3379 | |||||
| 3380 | for (unsigned Idx = 0; Idx < FTy->getNumParams(); ++Idx) { | ||||
| 3381 | if (Attrs.hasParamAttr(Idx, Attribute::Nest)) | ||||
| 3382 | SawNest = true; | ||||
| 3383 | if (Attrs.hasParamAttr(Idx, Attribute::Returned)) | ||||
| 3384 | SawReturned = true; | ||||
| 3385 | } | ||||
| 3386 | |||||
| 3387 | // Check attributes on the varargs part. | ||||
| 3388 | for (unsigned Idx = FTy->getNumParams(); Idx < Call.arg_size(); ++Idx) { | ||||
| 3389 | Type *Ty = Call.getArgOperand(Idx)->getType(); | ||||
| 3390 | AttributeSet ArgAttrs = Attrs.getParamAttrs(Idx); | ||||
| 3391 | verifyParameterAttrs(ArgAttrs, Ty, &Call); | ||||
| 3392 | |||||
| 3393 | if (ArgAttrs.hasAttribute(Attribute::Nest)) { | ||||
| 3394 | Check(!SawNest, "More than one parameter has attribute nest!", Call)do { if (!(!SawNest)) { CheckFailed("More than one parameter has attribute nest!" , Call); return; } } while (false); | ||||
| 3395 | SawNest = true; | ||||
| 3396 | } | ||||
| 3397 | |||||
| 3398 | if (ArgAttrs.hasAttribute(Attribute::Returned)) { | ||||
| 3399 | Check(!SawReturned, "More than one parameter has attribute returned!",do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false) | ||||
| 3400 | Call)do { if (!(!SawReturned)) { CheckFailed("More than one parameter has attribute returned!" , Call); return; } } while (false); | ||||
| 3401 | Check(Ty->canLosslesslyBitCastTo(FTy->getReturnType()),do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3402 | "Incompatible argument and return types for 'returned' "do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3403 | "attribute",do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false) | ||||
| 3404 | Call)do { if (!(Ty->canLosslesslyBitCastTo(FTy->getReturnType ()))) { CheckFailed("Incompatible argument and return types for 'returned' " "attribute", Call); return; } } while (false); | ||||
| 3405 | SawReturned = true; | ||||
| 3406 | } | ||||
| 3407 | |||||
| 3408 | // Statepoint intrinsic is vararg but the wrapped function may be not. | ||||
| 3409 | // Allow sret here and check the wrapped function in verifyStatepoint. | ||||
| 3410 | if (!Call.getCalledFunction() || | ||||
| 3411 | Call.getCalledFunction()->getIntrinsicID() != | ||||
| 3412 | Intrinsic::experimental_gc_statepoint) | ||||
| 3413 | Check(!ArgAttrs.hasAttribute(Attribute::StructRet),do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 3414 | "Attribute 'sret' cannot be used for vararg call arguments!",do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false) | ||||
| 3415 | Call)do { if (!(!ArgAttrs.hasAttribute(Attribute::StructRet))) { CheckFailed ("Attribute 'sret' cannot be used for vararg call arguments!" , Call); return; } } while (false); | ||||
| 3416 | |||||
| 3417 | if (ArgAttrs.hasAttribute(Attribute::InAlloca)) | ||||
| 3418 | Check(Idx == Call.arg_size() - 1,do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false) | ||||
| 3419 | "inalloca isn't on the last argument!", Call)do { if (!(Idx == Call.arg_size() - 1)) { CheckFailed("inalloca isn't on the last argument!" , Call); return; } } while (false); | ||||
| 3420 | } | ||||
| 3421 | } | ||||
| 3422 | |||||
| 3423 | // Verify that there's no metadata unless it's a direct call to an intrinsic. | ||||
| 3424 | if (!IsIntrinsic) { | ||||
| 3425 | for (Type *ParamTy : FTy->params()) { | ||||
| 3426 | Check(!ParamTy->isMetadataTy(),do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
| 3427 | "Function has metadata parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isMetadataTy())) { CheckFailed("Function has metadata parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
| 3428 | Check(!ParamTy->isTokenTy(),do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false) | ||||
| 3429 | "Function has token parameter but isn't an intrinsic", Call)do { if (!(!ParamTy->isTokenTy())) { CheckFailed("Function has token parameter but isn't an intrinsic" , Call); return; } } while (false); | ||||
| 3430 | } | ||||
| 3431 | } | ||||
| 3432 | |||||
| 3433 | // Verify that indirect calls don't return tokens. | ||||
| 3434 | if (!Call.getCalledFunction()) { | ||||
| 3435 | Check(!FTy->getReturnType()->isTokenTy(),do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false) | ||||
| 3436 | "Return type cannot be token for indirect call!")do { if (!(!FTy->getReturnType()->isTokenTy())) { CheckFailed ("Return type cannot be token for indirect call!"); return; } } while (false); | ||||
| 3437 | Check(!FTy->getReturnType()->isX86_AMXTy(),do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false) | ||||
| 3438 | "Return type cannot be x86_amx for indirect call!")do { if (!(!FTy->getReturnType()->isX86_AMXTy())) { CheckFailed ("Return type cannot be x86_amx for indirect call!"); return; } } while (false); | ||||
| 3439 | } | ||||
| 3440 | |||||
| 3441 | if (Function *F = Call.getCalledFunction()) | ||||
| 3442 | if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) | ||||
| 3443 | visitIntrinsicCall(ID, Call); | ||||
| 3444 | |||||
| 3445 | // Verify that a callsite has at most one "deopt", at most one "funclet", at | ||||
| 3446 | // most one "gc-transition", at most one "cfguardtarget", at most one | ||||
| 3447 | // "preallocated" operand bundle, and at most one "ptrauth" operand bundle. | ||||
| 3448 | bool FoundDeoptBundle = false, FoundFuncletBundle = false, | ||||
| 3449 | FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false, | ||||
| 3450 | FoundPreallocatedBundle = false, FoundGCLiveBundle = false, | ||||
| 3451 | FoundPtrauthBundle = false, FoundKCFIBundle = false, | ||||
| 3452 | FoundAttachedCallBundle = false; | ||||
| 3453 | for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) { | ||||
| 3454 | OperandBundleUse BU = Call.getOperandBundleAt(i); | ||||
| 3455 | uint32_t Tag = BU.getTagID(); | ||||
| 3456 | if (Tag == LLVMContext::OB_deopt) { | ||||
| 3457 | Check(!FoundDeoptBundle, "Multiple deopt operand bundles", Call)do { if (!(!FoundDeoptBundle)) { CheckFailed("Multiple deopt operand bundles" , Call); return; } } while (false); | ||||
| 3458 | FoundDeoptBundle = true; | ||||
| 3459 | } else if (Tag == LLVMContext::OB_gc_transition) { | ||||
| 3460 | Check(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false) | ||||
| 3461 | Call)do { if (!(!FoundGCTransitionBundle)) { CheckFailed("Multiple gc-transition operand bundles" , Call); return; } } while (false); | ||||
| 3462 | FoundGCTransitionBundle = true; | ||||
| 3463 | } else if (Tag == LLVMContext::OB_funclet) { | ||||
| 3464 | Check(!FoundFuncletBundle, "Multiple funclet operand bundles", Call)do { if (!(!FoundFuncletBundle)) { CheckFailed("Multiple funclet operand bundles" , Call); return; } } while (false); | ||||
| 3465 | FoundFuncletBundle = true; | ||||
| 3466 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false) | ||||
| 3467 | "Expected exactly one funclet bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one funclet bundle operand" , Call); return; } } while (false); | ||||
| 3468 | Check(isa<FuncletPadInst>(BU.Inputs.front()),do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
| 3469 | "Funclet bundle operands should correspond to a FuncletPadInst",do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false) | ||||
| 3470 | Call)do { if (!(isa<FuncletPadInst>(BU.Inputs.front()))) { CheckFailed ("Funclet bundle operands should correspond to a FuncletPadInst" , Call); return; } } while (false); | ||||
| 3471 | } else if (Tag == LLVMContext::OB_cfguardtarget) { | ||||
| 3472 | Check(!FoundCFGuardTargetBundle, "Multiple CFGuardTarget operand bundles",do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false) | ||||
| 3473 | Call)do { if (!(!FoundCFGuardTargetBundle)) { CheckFailed("Multiple CFGuardTarget operand bundles" , Call); return; } } while (false); | ||||
| 3474 | FoundCFGuardTargetBundle = true; | ||||
| 3475 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false) | ||||
| 3476 | "Expected exactly one cfguardtarget bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one cfguardtarget bundle operand" , Call); return; } } while (false); | ||||
| 3477 | } else if (Tag == LLVMContext::OB_ptrauth) { | ||||
| 3478 | Check(!FoundPtrauthBundle, "Multiple ptrauth operand bundles", Call)do { if (!(!FoundPtrauthBundle)) { CheckFailed("Multiple ptrauth operand bundles" , Call); return; } } while (false); | ||||
| 3479 | FoundPtrauthBundle = true; | ||||
| 3480 | Check(BU.Inputs.size() == 2,do { if (!(BU.Inputs.size() == 2)) { CheckFailed("Expected exactly two ptrauth bundle operands" , Call); return; } } while (false) | ||||
| 3481 | "Expected exactly two ptrauth bundle operands", Call)do { if (!(BU.Inputs.size() == 2)) { CheckFailed("Expected exactly two ptrauth bundle operands" , Call); return; } } while (false); | ||||
| 3482 | Check(isa<ConstantInt>(BU.Inputs[0]) &&do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false) | ||||
| 3483 | BU.Inputs[0]->getType()->isIntegerTy(32),do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false) | ||||
| 3484 | "Ptrauth bundle key operand must be an i32 constant", Call)do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Ptrauth bundle key operand must be an i32 constant", Call); return ; } } while (false); | ||||
| 3485 | Check(BU.Inputs[1]->getType()->isIntegerTy(64),do { if (!(BU.Inputs[1]->getType()->isIntegerTy(64))) { CheckFailed("Ptrauth bundle discriminator operand must be an i64" , Call); return; } } while (false) | ||||
| 3486 | "Ptrauth bundle discriminator operand must be an i64", Call)do { if (!(BU.Inputs[1]->getType()->isIntegerTy(64))) { CheckFailed("Ptrauth bundle discriminator operand must be an i64" , Call); return; } } while (false); | ||||
| 3487 | } else if (Tag == LLVMContext::OB_kcfi) { | ||||
| 3488 | Check(!FoundKCFIBundle, "Multiple kcfi operand bundles", Call)do { if (!(!FoundKCFIBundle)) { CheckFailed("Multiple kcfi operand bundles" , Call); return; } } while (false); | ||||
| 3489 | FoundKCFIBundle = true; | ||||
| 3490 | Check(BU.Inputs.size() == 1, "Expected exactly one kcfi bundle operand",do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one kcfi bundle operand" , Call); return; } } while (false) | ||||
| 3491 | Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one kcfi bundle operand" , Call); return; } } while (false); | ||||
| 3492 | Check(isa<ConstantInt>(BU.Inputs[0]) &&do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false) | ||||
| 3493 | BU.Inputs[0]->getType()->isIntegerTy(32),do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false) | ||||
| 3494 | "Kcfi bundle operand must be an i32 constant", Call)do { if (!(isa<ConstantInt>(BU.Inputs[0]) && BU .Inputs[0]->getType()->isIntegerTy(32))) { CheckFailed( "Kcfi bundle operand must be an i32 constant", Call); return; } } while (false); | ||||
| 3495 | } else if (Tag == LLVMContext::OB_preallocated) { | ||||
| 3496 | Check(!FoundPreallocatedBundle, "Multiple preallocated operand bundles",do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false) | ||||
| 3497 | Call)do { if (!(!FoundPreallocatedBundle)) { CheckFailed("Multiple preallocated operand bundles" , Call); return; } } while (false); | ||||
| 3498 | FoundPreallocatedBundle = true; | ||||
| 3499 | Check(BU.Inputs.size() == 1,do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false) | ||||
| 3500 | "Expected exactly one preallocated bundle operand", Call)do { if (!(BU.Inputs.size() == 1)) { CheckFailed("Expected exactly one preallocated bundle operand" , Call); return; } } while (false); | ||||
| 3501 | auto Input = dyn_cast<IntrinsicInst>(BU.Inputs.front()); | ||||
| 3502 | Check(Input &&do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3503 | Input->getIntrinsicID() == Intrinsic::call_preallocated_setup,do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3504 | "\"preallocated\" argument must be a token from "do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3505 | "llvm.call.preallocated.setup",do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ) | ||||
| 3506 | Call)do { if (!(Input && Input->getIntrinsicID() == Intrinsic ::call_preallocated_setup)) { CheckFailed("\"preallocated\" argument must be a token from " "llvm.call.preallocated.setup", Call); return; } } while (false ); | ||||
| 3507 | } else if (Tag == LLVMContext::OB_gc_live) { | ||||
| 3508 | Check(!FoundGCLiveBundle, "Multiple gc-live operand bundles", Call)do { if (!(!FoundGCLiveBundle)) { CheckFailed("Multiple gc-live operand bundles" , Call); return; } } while (false); | ||||
| 3509 | FoundGCLiveBundle = true; | ||||
| 3510 | } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) { | ||||
| 3511 | Check(!FoundAttachedCallBundle,do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false) | ||||
| 3512 | "Multiple \"clang.arc.attachedcall\" operand bundles", Call)do { if (!(!FoundAttachedCallBundle)) { CheckFailed("Multiple \"clang.arc.attachedcall\" operand bundles" , Call); return; } } while (false); | ||||
| 3513 | FoundAttachedCallBundle = true; | ||||
| 3514 | verifyAttachedCallBundle(Call, BU); | ||||
| 3515 | } | ||||
| 3516 | } | ||||
| 3517 | |||||
| 3518 | // Verify that callee and callsite agree on whether to use pointer auth. | ||||
| 3519 | Check(!(Call.getCalledFunction() && FoundPtrauthBundle),do { if (!(!(Call.getCalledFunction() && FoundPtrauthBundle ))) { CheckFailed("Direct call cannot have a ptrauth bundle", Call); return; } } while (false) | ||||
| 3520 | "Direct call cannot have a ptrauth bundle", Call)do { if (!(!(Call.getCalledFunction() && FoundPtrauthBundle ))) { CheckFailed("Direct call cannot have a ptrauth bundle", Call); return; } } while (false); | ||||
| 3521 | |||||
| 3522 | // Verify that each inlinable callsite of a debug-info-bearing function in a | ||||
| 3523 | // debug-info-bearing function has a debug location attached to it. Failure to | ||||
| 3524 | // do so causes assertion failures when the inliner sets up inline scope info | ||||
| 3525 | // (Interposable functions are not inlinable, neither are functions without | ||||
| 3526 | // definitions.) | ||||
| 3527 | if (Call.getFunction()->getSubprogram() && Call.getCalledFunction() && | ||||
| 3528 | !Call.getCalledFunction()->isInterposable() && | ||||
| 3529 | !Call.getCalledFunction()->isDeclaration() && | ||||
| 3530 | Call.getCalledFunction()->getSubprogram()) | ||||
| 3531 | CheckDI(Call.getDebugLoc(),do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3532 | "inlinable function call in a function with "do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3533 | "debug info must have a !dbg location",do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false) | ||||
| 3534 | Call)do { if (!(Call.getDebugLoc())) { DebugInfoCheckFailed("inlinable function call in a function with " "debug info must have a !dbg location", Call); return; } } while (false); | ||||
| 3535 | |||||
| 3536 | if (Call.isInlineAsm()) | ||||
| 3537 | verifyInlineAsmCall(Call); | ||||
| 3538 | |||||
| 3539 | visitInstruction(Call); | ||||
| 3540 | } | ||||
| 3541 | |||||
| 3542 | void Verifier::verifyTailCCMustTailAttrs(const AttrBuilder &Attrs, | ||||
| 3543 | StringRef Context) { | ||||
| 3544 | Check(!Attrs.contains(Attribute::InAlloca),do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3545 | Twine("inalloca attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InAlloca))) { CheckFailed (Twine("inalloca attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3546 | Check(!Attrs.contains(Attribute::InReg),do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false) | ||||
| 3547 | Twine("inreg attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::InReg))) { CheckFailed( Twine("inreg attribute not allowed in ") + Context); return; } } while (false); | ||||
| 3548 | Check(!Attrs.contains(Attribute::SwiftError),do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3549 | Twine("swifterror attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::SwiftError))) { CheckFailed (Twine("swifterror attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3550 | Check(!Attrs.contains(Attribute::Preallocated),do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false) | ||||
| 3551 | Twine("preallocated attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::Preallocated))) { CheckFailed (Twine("preallocated attribute not allowed in ") + Context); return ; } } while (false); | ||||
| 3552 | Check(!Attrs.contains(Attribute::ByRef),do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false) | ||||
| 3553 | Twine("byref attribute not allowed in ") + Context)do { if (!(!Attrs.contains(Attribute::ByRef))) { CheckFailed( Twine("byref attribute not allowed in ") + Context); return; } } while (false); | ||||
| 3554 | } | ||||
| 3555 | |||||
| 3556 | /// Two types are "congruent" if they are identical, or if they are both pointer | ||||
| 3557 | /// types with different pointee types and the same address space. | ||||
| 3558 | static bool isTypeCongruent(Type *L, Type *R) { | ||||
| 3559 | if (L == R) | ||||
| 3560 | return true; | ||||
| 3561 | PointerType *PL = dyn_cast<PointerType>(L); | ||||
| 3562 | PointerType *PR = dyn_cast<PointerType>(R); | ||||
| 3563 | if (!PL || !PR) | ||||
| 3564 | return false; | ||||
| 3565 | return PL->getAddressSpace() == PR->getAddressSpace(); | ||||
| 3566 | } | ||||
| 3567 | |||||
| 3568 | static AttrBuilder getParameterABIAttributes(LLVMContext& C, unsigned I, AttributeList Attrs) { | ||||
| 3569 | static const Attribute::AttrKind ABIAttrs[] = { | ||||
| 3570 | Attribute::StructRet, Attribute::ByVal, Attribute::InAlloca, | ||||
| 3571 | Attribute::InReg, Attribute::StackAlignment, Attribute::SwiftSelf, | ||||
| 3572 | Attribute::SwiftAsync, Attribute::SwiftError, Attribute::Preallocated, | ||||
| 3573 | Attribute::ByRef}; | ||||
| 3574 | AttrBuilder Copy(C); | ||||
| 3575 | for (auto AK : ABIAttrs) { | ||||
| 3576 | Attribute Attr = Attrs.getParamAttrs(I).getAttribute(AK); | ||||
| 3577 | if (Attr.isValid()) | ||||
| 3578 | Copy.addAttribute(Attr); | ||||
| 3579 | } | ||||
| 3580 | |||||
| 3581 | // `align` is ABI-affecting only in combination with `byval` or `byref`. | ||||
| 3582 | if (Attrs.hasParamAttr(I, Attribute::Alignment) && | ||||
| 3583 | (Attrs.hasParamAttr(I, Attribute::ByVal) || | ||||
| 3584 | Attrs.hasParamAttr(I, Attribute::ByRef))) | ||||
| 3585 | Copy.addAlignmentAttr(Attrs.getParamAlignment(I)); | ||||
| 3586 | return Copy; | ||||
| 3587 | } | ||||
| 3588 | |||||
| 3589 | void Verifier::verifyMustTailCall(CallInst &CI) { | ||||
| 3590 | Check(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI)do { if (!(!CI.isInlineAsm())) { CheckFailed("cannot use musttail call with inline asm" , &CI); return; } } while (false); | ||||
| 3591 | |||||
| 3592 | Function *F = CI.getParent()->getParent(); | ||||
| 3593 | FunctionType *CallerTy = F->getFunctionType(); | ||||
| 3594 | FunctionType *CalleeTy = CI.getFunctionType(); | ||||
| 3595 | Check(CallerTy->isVarArg() == CalleeTy->isVarArg(),do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false) | ||||
| 3596 | "cannot guarantee tail call due to mismatched varargs", &CI)do { if (!(CallerTy->isVarArg() == CalleeTy->isVarArg() )) { CheckFailed("cannot guarantee tail call due to mismatched varargs" , &CI); return; } } while (false); | ||||
| 3597 | Check(isTypeCongruent(CallerTy->getReturnType(), CalleeTy->getReturnType()),do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false) | ||||
| 3598 | "cannot guarantee tail call due to mismatched return types", &CI)do { if (!(isTypeCongruent(CallerTy->getReturnType(), CalleeTy ->getReturnType()))) { CheckFailed("cannot guarantee tail call due to mismatched return types" , &CI); return; } } while (false); | ||||
| 3599 | |||||
| 3600 | // - The calling conventions of the caller and callee must match. | ||||
| 3601 | Check(F->getCallingConv() == CI.getCallingConv(),do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false) | ||||
| 3602 | "cannot guarantee tail call due to mismatched calling conv", &CI)do { if (!(F->getCallingConv() == CI.getCallingConv())) { CheckFailed ("cannot guarantee tail call due to mismatched calling conv", &CI); return; } } while (false); | ||||
| 3603 | |||||
| 3604 | // - The call must immediately precede a :ref:`ret <i_ret>` instruction, | ||||
| 3605 | // or a pointer bitcast followed by a ret instruction. | ||||
| 3606 | // - The ret instruction must return the (possibly bitcasted) value | ||||
| 3607 | // produced by the call or void. | ||||
| 3608 | Value *RetVal = &CI; | ||||
| 3609 | Instruction *Next = CI.getNextNode(); | ||||
| 3610 | |||||
| 3611 | // Handle the optional bitcast. | ||||
| 3612 | if (BitCastInst *BI = dyn_cast_or_null<BitCastInst>(Next)) { | ||||
| 3613 | Check(BI->getOperand(0) == RetVal,do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false) | ||||
| 3614 | "bitcast following musttail call must use the call", BI)do { if (!(BI->getOperand(0) == RetVal)) { CheckFailed("bitcast following musttail call must use the call" , BI); return; } } while (false); | ||||
| 3615 | RetVal = BI; | ||||
| 3616 | Next = BI->getNextNode(); | ||||
| 3617 | } | ||||
| 3618 | |||||
| 3619 | // Check the return. | ||||
| 3620 | ReturnInst *Ret = dyn_cast_or_null<ReturnInst>(Next); | ||||
| 3621 | Check(Ret, "musttail call must precede a ret with an optional bitcast", &CI)do { if (!(Ret)) { CheckFailed("musttail call must precede a ret with an optional bitcast" , &CI); return; } } while (false); | ||||
| 3622 | Check(!Ret->getReturnValue() || Ret->getReturnValue() == RetVal ||do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
| 3623 | isa<UndefValue>(Ret->getReturnValue()),do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false) | ||||
| 3624 | "musttail call result must be returned", Ret)do { if (!(!Ret->getReturnValue() || Ret->getReturnValue () == RetVal || isa<UndefValue>(Ret->getReturnValue( )))) { CheckFailed("musttail call result must be returned", Ret ); return; } } while (false); | ||||
| 3625 | |||||
| 3626 | AttributeList CallerAttrs = F->getAttributes(); | ||||
| 3627 | AttributeList CalleeAttrs = CI.getAttributes(); | ||||
| 3628 | if (CI.getCallingConv() == CallingConv::SwiftTail || | ||||
| 3629 | CI.getCallingConv() == CallingConv::Tail) { | ||||
| 3630 | StringRef CCName = | ||||
| 3631 | CI.getCallingConv() == CallingConv::Tail ? "tailcc" : "swifttailcc"; | ||||
| 3632 | |||||
| 3633 | // - Only sret, byval, swiftself, and swiftasync ABI-impacting attributes | ||||
| 3634 | // are allowed in swifttailcc call | ||||
| 3635 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3636 | AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs); | ||||
| 3637 | SmallString<32> Context{CCName, StringRef(" musttail caller")}; | ||||
| 3638 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
| 3639 | } | ||||
| 3640 | for (unsigned I = 0, E = CalleeTy->getNumParams(); I != E; ++I) { | ||||
| 3641 | AttrBuilder ABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs); | ||||
| 3642 | SmallString<32> Context{CCName, StringRef(" musttail callee")}; | ||||
| 3643 | verifyTailCCMustTailAttrs(ABIAttrs, Context); | ||||
| 3644 | } | ||||
| 3645 | // - Varargs functions are not allowed | ||||
| 3646 | Check(!CallerTy->isVarArg(), Twine("cannot guarantee ") + CCName +do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false) | ||||
| 3647 | " tail call for varargs function")do { if (!(!CallerTy->isVarArg())) { CheckFailed(Twine("cannot guarantee " ) + CCName + " tail call for varargs function"); return; } } while (false); | ||||
| 3648 | return; | ||||
| 3649 | } | ||||
| 3650 | |||||
| 3651 | // - The caller and callee prototypes must match. Pointer types of | ||||
| 3652 | // parameters or return types may differ in pointee type, but not | ||||
| 3653 | // address space. | ||||
| 3654 | if (!CI.getCalledFunction() || !CI.getCalledFunction()->isIntrinsic()) { | ||||
| 3655 | Check(CallerTy->getNumParams() == CalleeTy->getNumParams(),do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false) | ||||
| 3656 | "cannot guarantee tail call due to mismatched parameter counts", &CI)do { if (!(CallerTy->getNumParams() == CalleeTy->getNumParams ())) { CheckFailed("cannot guarantee tail call due to mismatched parameter counts" , &CI); return; } } while (false); | ||||
| 3657 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3658 | Check(do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
| 3659 | isTypeCongruent(CallerTy->getParamType(I), CalleeTy->getParamType(I)),do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false) | ||||
| 3660 | "cannot guarantee tail call due to mismatched parameter types", &CI)do { if (!(isTypeCongruent(CallerTy->getParamType(I), CalleeTy ->getParamType(I)))) { CheckFailed("cannot guarantee tail call due to mismatched parameter types" , &CI); return; } } while (false); | ||||
| 3661 | } | ||||
| 3662 | } | ||||
| 3663 | |||||
| 3664 | // - All ABI-impacting function attributes, such as sret, byval, inreg, | ||||
| 3665 | // returned, preallocated, and inalloca, must match. | ||||
| 3666 | for (unsigned I = 0, E = CallerTy->getNumParams(); I != E; ++I) { | ||||
| 3667 | AttrBuilder CallerABIAttrs = getParameterABIAttributes(F->getContext(), I, CallerAttrs); | ||||
| 3668 | AttrBuilder CalleeABIAttrs = getParameterABIAttributes(F->getContext(), I, CalleeAttrs); | ||||
| 3669 | Check(CallerABIAttrs == CalleeABIAttrs,do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3670 | "cannot guarantee tail call due to mismatched ABI impacting "do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3671 | "function attributes",do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false) | ||||
| 3672 | &CI, CI.getOperand(I))do { if (!(CallerABIAttrs == CalleeABIAttrs)) { CheckFailed("cannot guarantee tail call due to mismatched ABI impacting " "function attributes", &CI, CI.getOperand(I)); return; } } while (false); | ||||
| 3673 | } | ||||
| 3674 | } | ||||
| 3675 | |||||
| 3676 | void Verifier::visitCallInst(CallInst &CI) { | ||||
| 3677 | visitCallBase(CI); | ||||
| 3678 | |||||
| 3679 | if (CI.isMustTailCall()) | ||||
| 3680 | verifyMustTailCall(CI); | ||||
| 3681 | } | ||||
| 3682 | |||||
| 3683 | void Verifier::visitInvokeInst(InvokeInst &II) { | ||||
| 3684 | visitCallBase(II); | ||||
| 3685 | |||||
| 3686 | // Verify that the first non-PHI instruction of the unwind destination is an | ||||
| 3687 | // exception handling instruction. | ||||
| 3688 | Check(do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3689 | II.getUnwindDest()->isEHPad(),do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3690 | "The unwind destination does not have an exception handling instruction!",do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false) | ||||
| 3691 | &II)do { if (!(II.getUnwindDest()->isEHPad())) { CheckFailed("The unwind destination does not have an exception handling instruction!" , &II); return; } } while (false); | ||||
| 3692 | |||||
| 3693 | visitTerminator(II); | ||||
| 3694 | } | ||||
| 3695 | |||||
| 3696 | /// visitUnaryOperator - Check the argument to the unary operator. | ||||
| 3697 | /// | ||||
| 3698 | void Verifier::visitUnaryOperator(UnaryOperator &U) { | ||||
| 3699 | Check(U.getType() == U.getOperand(0)->getType(),do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3700 | "Unary operators must have same type for"do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3701 | "operands and result!",do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false) | ||||
| 3702 | &U)do { if (!(U.getType() == U.getOperand(0)->getType())) { CheckFailed ("Unary operators must have same type for" "operands and result!" , &U); return; } } while (false); | ||||
| 3703 | |||||
| 3704 | switch (U.getOpcode()) { | ||||
| 3705 | // Check that floating-point arithmetic operators are only used with | ||||
| 3706 | // floating-point operands. | ||||
| 3707 | case Instruction::FNeg: | ||||
| 3708 | Check(U.getType()->isFPOrFPVectorTy(),do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false) | ||||
| 3709 | "FNeg operator only works with float types!", &U)do { if (!(U.getType()->isFPOrFPVectorTy())) { CheckFailed ("FNeg operator only works with float types!", &U); return ; } } while (false); | ||||
| 3710 | break; | ||||
| 3711 | default: | ||||
| 3712 | llvm_unreachable("Unknown UnaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown UnaryOperator opcode!" , "llvm/lib/IR/Verifier.cpp", 3712); | ||||
| 3713 | } | ||||
| 3714 | |||||
| 3715 | visitInstruction(U); | ||||
| 3716 | } | ||||
| 3717 | |||||
| 3718 | /// visitBinaryOperator - Check that both arguments to the binary operator are | ||||
| 3719 | /// of the same type! | ||||
| 3720 | /// | ||||
| 3721 | void Verifier::visitBinaryOperator(BinaryOperator &B) { | ||||
| 3722 | Check(B.getOperand(0)->getType() == B.getOperand(1)->getType(),do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false) | ||||
| 3723 | "Both operands to a binary operator are not of the same type!", &B)do { if (!(B.getOperand(0)->getType() == B.getOperand(1)-> getType())) { CheckFailed("Both operands to a binary operator are not of the same type!" , &B); return; } } while (false); | ||||
| 3724 | |||||
| 3725 | switch (B.getOpcode()) { | ||||
| 3726 | // Check that integer arithmetic operators are only used with | ||||
| 3727 | // integral operands. | ||||
| 3728 | case Instruction::Add: | ||||
| 3729 | case Instruction::Sub: | ||||
| 3730 | case Instruction::Mul: | ||||
| 3731 | case Instruction::SDiv: | ||||
| 3732 | case Instruction::UDiv: | ||||
| 3733 | case Instruction::SRem: | ||||
| 3734 | case Instruction::URem: | ||||
| 3735 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false) | ||||
| 3736 | "Integer arithmetic operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Integer arithmetic operators only work with integral types!" , &B); return; } } while (false); | ||||
| 3737 | Check(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3738 | "Integer arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3739 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3740 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Integer arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
| 3741 | break; | ||||
| 3742 | // Check that floating-point arithmetic operators are only used with | ||||
| 3743 | // floating-point operands. | ||||
| 3744 | case Instruction::FAdd: | ||||
| 3745 | case Instruction::FSub: | ||||
| 3746 | case Instruction::FMul: | ||||
| 3747 | case Instruction::FDiv: | ||||
| 3748 | case Instruction::FRem: | ||||
| 3749 | Check(B.getType()->isFPOrFPVectorTy(),do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3750 | "Floating-point arithmetic operators only work with "do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3751 | "floating-point types!",do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false) | ||||
| 3752 | &B)do { if (!(B.getType()->isFPOrFPVectorTy())) { CheckFailed ("Floating-point arithmetic operators only work with " "floating-point types!" , &B); return; } } while (false); | ||||
| 3753 | Check(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3754 | "Floating-point arithmetic operators must have same type "do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3755 | "for operands and result!",do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false) | ||||
| 3756 | &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Floating-point arithmetic operators must have same type " "for operands and result!" , &B); return; } } while (false); | ||||
| 3757 | break; | ||||
| 3758 | // Check that logical operators are only used with integral operands. | ||||
| 3759 | case Instruction::And: | ||||
| 3760 | case Instruction::Or: | ||||
| 3761 | case Instruction::Xor: | ||||
| 3762 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false) | ||||
| 3763 | "Logical operators only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Logical operators only work with integral types!", &B); return; } } while (false); | ||||
| 3764 | Check(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false) | ||||
| 3765 | "Logical operators must have same type for operands and result!", &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Logical operators must have same type for operands and result!" , &B); return; } } while (false); | ||||
| 3766 | break; | ||||
| 3767 | case Instruction::Shl: | ||||
| 3768 | case Instruction::LShr: | ||||
| 3769 | case Instruction::AShr: | ||||
| 3770 | Check(B.getType()->isIntOrIntVectorTy(),do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false) | ||||
| 3771 | "Shifts only work with integral types!", &B)do { if (!(B.getType()->isIntOrIntVectorTy())) { CheckFailed ("Shifts only work with integral types!", &B); return; } } while (false); | ||||
| 3772 | Check(B.getType() == B.getOperand(0)->getType(),do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false) | ||||
| 3773 | "Shift return type must be same as operands!", &B)do { if (!(B.getType() == B.getOperand(0)->getType())) { CheckFailed ("Shift return type must be same as operands!", &B); return ; } } while (false); | ||||
| 3774 | break; | ||||
| 3775 | default: | ||||
| 3776 | llvm_unreachable("Unknown BinaryOperator opcode!")::llvm::llvm_unreachable_internal("Unknown BinaryOperator opcode!" , "llvm/lib/IR/Verifier.cpp", 3776); | ||||
| 3777 | } | ||||
| 3778 | |||||
| 3779 | visitInstruction(B); | ||||
| 3780 | } | ||||
| 3781 | |||||
| 3782 | void Verifier::visitICmpInst(ICmpInst &IC) { | ||||
| 3783 | // Check that the operands are the same type | ||||
| 3784 | Type *Op0Ty = IC.getOperand(0)->getType(); | ||||
| 3785 | Type *Op1Ty = IC.getOperand(1)->getType(); | ||||
| 3786 | Check(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false) | ||||
| 3787 | "Both operands to ICmp instruction are not of the same type!", &IC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to ICmp instruction are not of the same type!" , &IC); return; } } while (false); | ||||
| 3788 | // Check that the operands are the right type | ||||
| 3789 | Check(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy(),do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false) | ||||
| 3790 | "Invalid operand types for ICmp instruction", &IC)do { if (!(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPtrOrPtrVectorTy ())) { CheckFailed("Invalid operand types for ICmp instruction" , &IC); return; } } while (false); | ||||
| 3791 | // Check that the predicate is valid. | ||||
| 3792 | Check(IC.isIntPredicate(), "Invalid predicate in ICmp instruction!", &IC)do { if (!(IC.isIntPredicate())) { CheckFailed("Invalid predicate in ICmp instruction!" , &IC); return; } } while (false); | ||||
| 3793 | |||||
| 3794 | visitInstruction(IC); | ||||
| 3795 | } | ||||
| 3796 | |||||
| 3797 | void Verifier::visitFCmpInst(FCmpInst &FC) { | ||||
| 3798 | // Check that the operands are the same type | ||||
| 3799 | Type *Op0Ty = FC.getOperand(0)->getType(); | ||||
| 3800 | Type *Op1Ty = FC.getOperand(1)->getType(); | ||||
| 3801 | Check(Op0Ty == Op1Ty,do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false) | ||||
| 3802 | "Both operands to FCmp instruction are not of the same type!", &FC)do { if (!(Op0Ty == Op1Ty)) { CheckFailed("Both operands to FCmp instruction are not of the same type!" , &FC); return; } } while (false); | ||||
| 3803 | // Check that the operands are the right type | ||||
| 3804 | Check(Op0Ty->isFPOrFPVectorTy(), "Invalid operand types for FCmp instruction",do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false) | ||||
| 3805 | &FC)do { if (!(Op0Ty->isFPOrFPVectorTy())) { CheckFailed("Invalid operand types for FCmp instruction" , &FC); return; } } while (false); | ||||
| 3806 | // Check that the predicate is valid. | ||||
| 3807 | Check(FC.isFPPredicate(), "Invalid predicate in FCmp instruction!", &FC)do { if (!(FC.isFPPredicate())) { CheckFailed("Invalid predicate in FCmp instruction!" , &FC); return; } } while (false); | ||||
| 3808 | |||||
| 3809 | visitInstruction(FC); | ||||
| 3810 | } | ||||
| 3811 | |||||
| 3812 | void Verifier::visitExtractElementInst(ExtractElementInst &EI) { | ||||
| 3813 | Check(ExtractElementInst::isValidOperands(EI.getOperand(0), EI.getOperand(1)),do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false) | ||||
| 3814 | "Invalid extractelement operands!", &EI)do { if (!(ExtractElementInst::isValidOperands(EI.getOperand( 0), EI.getOperand(1)))) { CheckFailed("Invalid extractelement operands!" , &EI); return; } } while (false); | ||||
| 3815 | visitInstruction(EI); | ||||
| 3816 | } | ||||
| 3817 | |||||
| 3818 | void Verifier::visitInsertElementInst(InsertElementInst &IE) { | ||||
| 3819 | Check(InsertElementInst::isValidOperands(IE.getOperand(0), IE.getOperand(1),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
| 3820 | IE.getOperand(2)),do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false) | ||||
| 3821 | "Invalid insertelement operands!", &IE)do { if (!(InsertElementInst::isValidOperands(IE.getOperand(0 ), IE.getOperand(1), IE.getOperand(2)))) { CheckFailed("Invalid insertelement operands!" , &IE); return; } } while (false); | ||||
| 3822 | visitInstruction(IE); | ||||
| 3823 | } | ||||
| 3824 | |||||
| 3825 | void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) { | ||||
| 3826 | Check(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
| 3827 | SV.getShuffleMask()),do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false) | ||||
| 3828 | "Invalid shufflevector operands!", &SV)do { if (!(ShuffleVectorInst::isValidOperands(SV.getOperand(0 ), SV.getOperand(1), SV.getShuffleMask()))) { CheckFailed("Invalid shufflevector operands!" , &SV); return; } } while (false); | ||||
| 3829 | visitInstruction(SV); | ||||
| 3830 | } | ||||
| 3831 | |||||
| 3832 | void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { | ||||
| 3833 | Type *TargetTy = GEP.getPointerOperandType()->getScalarType(); | ||||
| 3834 | |||||
| 3835 | Check(isa<PointerType>(TargetTy),do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false) | ||||
| 3836 | "GEP base pointer is not a vector or a vector of pointers", &GEP)do { if (!(isa<PointerType>(TargetTy))) { CheckFailed("GEP base pointer is not a vector or a vector of pointers" , &GEP); return; } } while (false); | ||||
| 3837 | Check(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP)do { if (!(GEP.getSourceElementType()->isSized())) { CheckFailed ("GEP into unsized type!", &GEP); return; } } while (false ); | ||||
| 3838 | |||||
| 3839 | SmallVector<Value *, 16> Idxs(GEP.indices()); | ||||
| 3840 | Check(do { if (!(all_of(Idxs, [](Value *V) { return V->getType() ->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
| 3841 | all_of(Idxs, [](Value *V) { return V->getType()->isIntOrIntVectorTy(); }),do { if (!(all_of(Idxs, [](Value *V) { return V->getType() ->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false) | ||||
| 3842 | "GEP indexes must be integers", &GEP)do { if (!(all_of(Idxs, [](Value *V) { return V->getType() ->isIntOrIntVectorTy(); }))) { CheckFailed("GEP indexes must be integers" , &GEP); return; } } while (false); | ||||
| 3843 | Type *ElTy = | ||||
| 3844 | GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs); | ||||
| 3845 | Check(ElTy, "Invalid indices for GEP pointer type!", &GEP)do { if (!(ElTy)) { CheckFailed("Invalid indices for GEP pointer type!" , &GEP); return; } } while (false); | ||||
| 3846 | |||||
| 3847 | Check(GEP.getType()->isPtrOrPtrVectorTy() &&do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
| 3848 | GEP.getResultElementType() == ElTy,do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false) | ||||
| 3849 | "GEP is not of right type for indices!", &GEP, ElTy)do { if (!(GEP.getType()->isPtrOrPtrVectorTy() && GEP .getResultElementType() == ElTy)) { CheckFailed("GEP is not of right type for indices!" , &GEP, ElTy); return; } } while (false); | ||||
| 3850 | |||||
| 3851 | if (auto *GEPVTy = dyn_cast<VectorType>(GEP.getType())) { | ||||
| 3852 | // Additional checks for vector GEPs. | ||||
| 3853 | ElementCount GEPWidth = GEPVTy->getElementCount(); | ||||
| 3854 | if (GEP.getPointerOperandType()->isVectorTy()) | ||||
| 3855 | Check(do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3856 | GEPWidth ==do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3857 | cast<VectorType>(GEP.getPointerOperandType())->getElementCount(),do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false) | ||||
| 3858 | "Vector GEP result width doesn't match operand's", &GEP)do { if (!(GEPWidth == cast<VectorType>(GEP.getPointerOperandType ())->getElementCount())) { CheckFailed("Vector GEP result width doesn't match operand's" , &GEP); return; } } while (false); | ||||
| 3859 | for (Value *Idx : Idxs) { | ||||
| 3860 | Type *IndexTy = Idx->getType(); | ||||
| 3861 | if (auto *IndexVTy = dyn_cast<VectorType>(IndexTy)) { | ||||
| 3862 | ElementCount IndexWidth = IndexVTy->getElementCount(); | ||||
| 3863 | Check(IndexWidth == GEPWidth, "Invalid GEP index vector width", &GEP)do { if (!(IndexWidth == GEPWidth)) { CheckFailed("Invalid GEP index vector width" , &GEP); return; } } while (false); | ||||
| 3864 | } | ||||
| 3865 | Check(IndexTy->isIntOrIntVectorTy(),do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false) | ||||
| 3866 | "All GEP indices should be of integer type")do { if (!(IndexTy->isIntOrIntVectorTy())) { CheckFailed("All GEP indices should be of integer type" ); return; } } while (false); | ||||
| 3867 | } | ||||
| 3868 | } | ||||
| 3869 | |||||
| 3870 | if (auto *PTy = dyn_cast<PointerType>(GEP.getType())) { | ||||
| 3871 | Check(GEP.getAddressSpace() == PTy->getAddressSpace(),do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false) | ||||
| 3872 | "GEP address space doesn't match type", &GEP)do { if (!(GEP.getAddressSpace() == PTy->getAddressSpace() )) { CheckFailed("GEP address space doesn't match type", & GEP); return; } } while (false); | ||||
| 3873 | } | ||||
| 3874 | |||||
| 3875 | visitInstruction(GEP); | ||||
| 3876 | } | ||||
| 3877 | |||||
| 3878 | static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { | ||||
| 3879 | return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); | ||||
| 3880 | } | ||||
| 3881 | |||||
| 3882 | void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { | ||||
| 3883 | assert(Range && Range == I.getMetadata(LLVMContext::MD_range) &&(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "llvm/lib/IR/Verifier.cpp", 3884, __extension__ __PRETTY_FUNCTION__ )) | ||||
| 3884 | "precondition violation")(static_cast <bool> (Range && Range == I.getMetadata (LLVMContext::MD_range) && "precondition violation") ? void (0) : __assert_fail ("Range && Range == I.getMetadata(LLVMContext::MD_range) && \"precondition violation\"" , "llvm/lib/IR/Verifier.cpp", 3884, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 3885 | |||||
| 3886 | unsigned NumOperands = Range->getNumOperands(); | ||||
| 3887 | Check(NumOperands % 2 == 0, "Unfinished range!", Range)do { if (!(NumOperands % 2 == 0)) { CheckFailed("Unfinished range!" , Range); return; } } while (false); | ||||
| 3888 | unsigned NumRanges = NumOperands / 2; | ||||
| 3889 | Check(NumRanges >= 1, "It should have at least one range!", Range)do { if (!(NumRanges >= 1)) { CheckFailed("It should have at least one range!" , Range); return; } } while (false); | ||||
| 3890 | |||||
| 3891 | ConstantRange LastRange(1, true); // Dummy initial value | ||||
| 3892 | for (unsigned i = 0; i < NumRanges; ++i) { | ||||
| 3893 | ConstantInt *Low = | ||||
| 3894 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i)); | ||||
| 3895 | Check(Low, "The lower limit must be an integer!", Low)do { if (!(Low)) { CheckFailed("The lower limit must be an integer!" , Low); return; } } while (false); | ||||
| 3896 | ConstantInt *High = | ||||
| 3897 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1)); | ||||
| 3898 | Check(High, "The upper limit must be an integer!", High)do { if (!(High)) { CheckFailed("The upper limit must be an integer!" , High); return; } } while (false); | ||||
| 3899 | Check(High->getType() == Low->getType() &&do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false) | ||||
| 3900 | High->getType() == Ty->getScalarType(),do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false) | ||||
| 3901 | "Range types must match instruction type!", &I)do { if (!(High->getType() == Low->getType() && High->getType() == Ty->getScalarType())) { CheckFailed ("Range types must match instruction type!", &I); return; } } while (false); | ||||
| 3902 | |||||
| 3903 | APInt HighV = High->getValue(); | ||||
| 3904 | APInt LowV = Low->getValue(); | ||||
| 3905 | ConstantRange CurRange(LowV, HighV); | ||||
| 3906 | Check(!CurRange.isEmptySet() && !CurRange.isFullSet(),do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false) | ||||
| 3907 | "Range must not be empty!", Range)do { if (!(!CurRange.isEmptySet() && !CurRange.isFullSet ())) { CheckFailed("Range must not be empty!", Range); return ; } } while (false); | ||||
| 3908 | if (i != 0) { | ||||
| 3909 | Check(CurRange.intersectWith(LastRange).isEmptySet(),do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
| 3910 | "Intervals are overlapping", Range)do { if (!(CurRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
| 3911 | Check(LowV.sgt(LastRange.getLower()), "Intervals are not in order",do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false) | ||||
| 3912 | Range)do { if (!(LowV.sgt(LastRange.getLower()))) { CheckFailed("Intervals are not in order" , Range); return; } } while (false); | ||||
| 3913 | Check(!isContiguous(CurRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
| 3914 | Range)do { if (!(!isContiguous(CurRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
| 3915 | } | ||||
| 3916 | LastRange = ConstantRange(LowV, HighV); | ||||
| 3917 | } | ||||
| 3918 | if (NumRanges > 2) { | ||||
| 3919 | APInt FirstLow = | ||||
| 3920 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue(); | ||||
| 3921 | APInt FirstHigh = | ||||
| 3922 | mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue(); | ||||
| 3923 | ConstantRange FirstRange(FirstLow, FirstHigh); | ||||
| 3924 | Check(FirstRange.intersectWith(LastRange).isEmptySet(),do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false) | ||||
| 3925 | "Intervals are overlapping", Range)do { if (!(FirstRange.intersectWith(LastRange).isEmptySet())) { CheckFailed("Intervals are overlapping", Range); return; } } while (false); | ||||
| 3926 | Check(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ) | ||||
| 3927 | Range)do { if (!(!isContiguous(FirstRange, LastRange))) { CheckFailed ("Intervals are contiguous", Range); return; } } while (false ); | ||||
| 3928 | } | ||||
| 3929 | } | ||||
| 3930 | |||||
| 3931 | void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { | ||||
| 3932 | unsigned Size = DL.getTypeSizeInBits(Ty); | ||||
| 3933 | Check(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I)do { if (!(Size >= 8)) { CheckFailed("atomic memory access' size must be byte-sized" , Ty, I); return; } } while (false); | ||||
| 3934 | Check(!(Size & (Size - 1)),do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false) | ||||
| 3935 | "atomic memory access' operand must have a power-of-two size", Ty, I)do { if (!(!(Size & (Size - 1)))) { CheckFailed("atomic memory access' operand must have a power-of-two size" , Ty, I); return; } } while (false); | ||||
| 3936 | } | ||||
| 3937 | |||||
| 3938 | void Verifier::visitLoadInst(LoadInst &LI) { | ||||
| 3939 | PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType()); | ||||
| 3940 | Check(PTy, "Load operand must be a pointer.", &LI)do { if (!(PTy)) { CheckFailed("Load operand must be a pointer." , &LI); return; } } while (false); | ||||
| 3941 | Type *ElTy = LI.getType(); | ||||
| 3942 | if (MaybeAlign A = LI.getAlign()) { | ||||
| 3943 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &LI); return; } } while (false) | ||||
| 3944 | "huge alignment values are unsupported", &LI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &LI); return; } } while (false); | ||||
| 3945 | } | ||||
| 3946 | Check(ElTy->isSized(), "loading unsized types is not allowed", &LI)do { if (!(ElTy->isSized())) { CheckFailed("loading unsized types is not allowed" , &LI); return; } } while (false); | ||||
| 3947 | if (LI.isAtomic()) { | ||||
| 3948 | Check(LI.getOrdering() != AtomicOrdering::Release &&do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
| 3949 | LI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false) | ||||
| 3950 | "Load cannot have Release ordering", &LI)do { if (!(LI.getOrdering() != AtomicOrdering::Release && LI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Load cannot have Release ordering", &LI); return; } } while (false); | ||||
| 3951 | Check(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3952 | "atomic load operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3953 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false) | ||||
| 3954 | ElTy, &LI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic load operand must have integer, pointer, or floating point " "type!", ElTy, &LI); return; } } while (false); | ||||
| 3955 | checkAtomicMemAccessSize(ElTy, &LI); | ||||
| 3956 | } else { | ||||
| 3957 | Check(LI.getSyncScopeID() == SyncScope::System,do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false) | ||||
| 3958 | "Non-atomic load cannot have SynchronizationScope specified", &LI)do { if (!(LI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic load cannot have SynchronizationScope specified" , &LI); return; } } while (false); | ||||
| 3959 | } | ||||
| 3960 | |||||
| 3961 | visitInstruction(LI); | ||||
| 3962 | } | ||||
| 3963 | |||||
| 3964 | void Verifier::visitStoreInst(StoreInst &SI) { | ||||
| 3965 | PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType()); | ||||
| 3966 | Check(PTy, "Store operand must be a pointer.", &SI)do { if (!(PTy)) { CheckFailed("Store operand must be a pointer." , &SI); return; } } while (false); | ||||
| 3967 | Type *ElTy = SI.getOperand(0)->getType(); | ||||
| 3968 | Check(PTy->isOpaqueOrPointeeTypeMatches(ElTy),do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false) | ||||
| 3969 | "Stored value type does not match pointer operand type!", &SI, ElTy)do { if (!(PTy->isOpaqueOrPointeeTypeMatches(ElTy))) { CheckFailed ("Stored value type does not match pointer operand type!", & SI, ElTy); return; } } while (false); | ||||
| 3970 | if (MaybeAlign A = SI.getAlign()) { | ||||
| 3971 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &SI); return; } } while (false) | ||||
| 3972 | "huge alignment values are unsupported", &SI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &SI); return; } } while (false); | ||||
| 3973 | } | ||||
| 3974 | Check(ElTy->isSized(), "storing unsized types is not allowed", &SI)do { if (!(ElTy->isSized())) { CheckFailed("storing unsized types is not allowed" , &SI); return; } } while (false); | ||||
| 3975 | if (SI.isAtomic()) { | ||||
| 3976 | Check(SI.getOrdering() != AtomicOrdering::Acquire &&do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
| 3977 | SI.getOrdering() != AtomicOrdering::AcquireRelease,do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false) | ||||
| 3978 | "Store cannot have Acquire ordering", &SI)do { if (!(SI.getOrdering() != AtomicOrdering::Acquire && SI.getOrdering() != AtomicOrdering::AcquireRelease)) { CheckFailed ("Store cannot have Acquire ordering", &SI); return; } } while (false); | ||||
| 3979 | Check(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy(),do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3980 | "atomic store operand must have integer, pointer, or floating point "do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3981 | "type!",do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false) | ||||
| 3982 | ElTy, &SI)do { if (!(ElTy->isIntOrPtrTy() || ElTy->isFloatingPointTy ())) { CheckFailed("atomic store operand must have integer, pointer, or floating point " "type!", ElTy, &SI); return; } } while (false); | ||||
| 3983 | checkAtomicMemAccessSize(ElTy, &SI); | ||||
| 3984 | } else { | ||||
| 3985 | Check(SI.getSyncScopeID() == SyncScope::System,do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false) | ||||
| 3986 | "Non-atomic store cannot have SynchronizationScope specified", &SI)do { if (!(SI.getSyncScopeID() == SyncScope::System)) { CheckFailed ("Non-atomic store cannot have SynchronizationScope specified" , &SI); return; } } while (false); | ||||
| 3987 | } | ||||
| 3988 | visitInstruction(SI); | ||||
| 3989 | } | ||||
| 3990 | |||||
| 3991 | /// Check that SwiftErrorVal is used as a swifterror argument in CS. | ||||
| 3992 | void Verifier::verifySwiftErrorCall(CallBase &Call, | ||||
| 3993 | const Value *SwiftErrorVal) { | ||||
| 3994 | for (const auto &I : llvm::enumerate(Call.args())) { | ||||
| 3995 | if (I.value() == SwiftErrorVal) { | ||||
| 3996 | Check(Call.paramHasAttr(I.index(), Attribute::SwiftError),do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3997 | "swifterror value when used in a callsite should be marked "do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3998 | "with swifterror attribute",do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false) | ||||
| 3999 | SwiftErrorVal, Call)do { if (!(Call.paramHasAttr(I.index(), Attribute::SwiftError ))) { CheckFailed("swifterror value when used in a callsite should be marked " "with swifterror attribute", SwiftErrorVal, Call); return; } } while (false); | ||||
| 4000 | } | ||||
| 4001 | } | ||||
| 4002 | } | ||||
| 4003 | |||||
| 4004 | void Verifier::verifySwiftErrorValue(const Value *SwiftErrorVal) { | ||||
| 4005 | // Check that swifterror value is only used by loads, stores, or as | ||||
| 4006 | // a swifterror argument. | ||||
| 4007 | for (const User *U : SwiftErrorVal->users()) { | ||||
| 4008 | Check(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) ||do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4009 | isa<InvokeInst>(U),do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4010 | "swifterror value can only be loaded and stored from, or "do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4011 | "as a swifterror argument!",do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4012 | SwiftErrorVal, U)do { if (!(isa<LoadInst>(U) || isa<StoreInst>(U) || isa<CallInst>(U) || isa<InvokeInst>(U))) { CheckFailed ("swifterror value can only be loaded and stored from, or " "as a swifterror argument!" , SwiftErrorVal, U); return; } } while (false); | ||||
| 4013 | // If it is used by a store, check it is the second operand. | ||||
| 4014 | if (auto StoreI = dyn_cast<StoreInst>(U)) | ||||
| 4015 | Check(StoreI->getOperand(1) == SwiftErrorVal,do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4016 | "swifterror value should be the second operand when used "do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4017 | "by stores",do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false) | ||||
| 4018 | SwiftErrorVal, U)do { if (!(StoreI->getOperand(1) == SwiftErrorVal)) { CheckFailed ("swifterror value should be the second operand when used " "by stores" , SwiftErrorVal, U); return; } } while (false); | ||||
| 4019 | if (auto *Call = dyn_cast<CallBase>(U)) | ||||
| 4020 | verifySwiftErrorCall(*const_cast<CallBase *>(Call), SwiftErrorVal); | ||||
| 4021 | } | ||||
| 4022 | } | ||||
| 4023 | |||||
| 4024 | void Verifier::visitAllocaInst(AllocaInst &AI) { | ||||
| 4025 | SmallPtrSet<Type*, 4> Visited; | ||||
| 4026 | Check(AI.getAllocatedType()->isSized(&Visited),do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false) | ||||
| 4027 | "Cannot allocate unsized type", &AI)do { if (!(AI.getAllocatedType()->isSized(&Visited))) { CheckFailed("Cannot allocate unsized type", &AI); return ; } } while (false); | ||||
| 4028 | Check(AI.getArraySize()->getType()->isIntegerTy(),do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false) | ||||
| 4029 | "Alloca array size must have integer type", &AI)do { if (!(AI.getArraySize()->getType()->isIntegerTy()) ) { CheckFailed("Alloca array size must have integer type", & AI); return; } } while (false); | ||||
| 4030 | if (MaybeAlign A = AI.getAlign()) { | ||||
| 4031 | Check(A->value() <= Value::MaximumAlignment,do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &AI); return; } } while (false) | ||||
| 4032 | "huge alignment values are unsupported", &AI)do { if (!(A->value() <= Value::MaximumAlignment)) { CheckFailed ("huge alignment values are unsupported", &AI); return; } } while (false); | ||||
| 4033 | } | ||||
| 4034 | |||||
| 4035 | if (AI.isSwiftError()) { | ||||
| 4036 | Check(AI.getAllocatedType()->isPointerTy(),do { if (!(AI.getAllocatedType()->isPointerTy())) { CheckFailed ("swifterror alloca must have pointer type", &AI); return ; } } while (false) | ||||
| 4037 | "swifterror alloca must have pointer type", &AI)do { if (!(AI.getAllocatedType()->isPointerTy())) { CheckFailed ("swifterror alloca must have pointer type", &AI); return ; } } while (false); | ||||
| 4038 | Check(!AI.isArrayAllocation(),do { if (!(!AI.isArrayAllocation())) { CheckFailed("swifterror alloca must not be array allocation" , &AI); return; } } while (false) | ||||
| 4039 | "swifterror alloca must not be array allocation", &AI)do { if (!(!AI.isArrayAllocation())) { CheckFailed("swifterror alloca must not be array allocation" , &AI); return; } } while (false); | ||||
| 4040 | verifySwiftErrorValue(&AI); | ||||
| 4041 | } | ||||
| 4042 | |||||
| 4043 | visitInstruction(AI); | ||||
| 4044 | } | ||||
| 4045 | |||||
| 4046 | void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { | ||||
| 4047 | Type *ElTy = CXI.getOperand(1)->getType(); | ||||
| 4048 | Check(ElTy->isIntOrPtrTy(),do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false) | ||||
| 4049 | "cmpxchg operand must have integer or pointer type", ElTy, &CXI)do { if (!(ElTy->isIntOrPtrTy())) { CheckFailed("cmpxchg operand must have integer or pointer type" , ElTy, &CXI); return; } } while (false); | ||||
| 4050 | checkAtomicMemAccessSize(ElTy, &CXI); | ||||
| 4051 | visitInstruction(CXI); | ||||
| 4052 | } | ||||
| 4053 | |||||
| 4054 | void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { | ||||
| 4055 | Check(RMWI.getOrdering() != AtomicOrdering::Unordered,do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false) | ||||
| 4056 | "atomicrmw instructions cannot be unordered.", &RMWI)do { if (!(RMWI.getOrdering() != AtomicOrdering::Unordered)) { CheckFailed("atomicrmw instructions cannot be unordered.", & RMWI); return; } } while (false); | ||||
| 4057 | auto Op = RMWI.getOperation(); | ||||
| 4058 | Type *ElTy = RMWI.getOperand(1)->getType(); | ||||
| 4059 | if (Op == AtomicRMWInst::Xchg) { | ||||
| 4060 | Check(ElTy->isIntegerTy() || ElTy->isFloatingPointTy() ||do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4061 | ElTy->isPointerTy(),do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4062 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4063 | " operand must have integer or floating point type!",do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4064 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy() || ElTy->isFloatingPointTy () || ElTy->isPointerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst ::getOperationName(Op) + " operand must have integer or floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
| 4065 | } else if (AtomicRMWInst::isFPOperation(Op)) { | ||||
| 4066 | Check(ElTy->isFloatingPointTy(),do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4067 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4068 | " operand must have floating point type!",do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4069 | &RMWI, ElTy)do { if (!(ElTy->isFloatingPointTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have floating point type!" , &RMWI, ElTy); return; } } while (false); | ||||
| 4070 | } else { | ||||
| 4071 | Check(ElTy->isIntegerTy(),do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4072 | "atomicrmw " + AtomicRMWInst::getOperationName(Op) +do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4073 | " operand must have integer type!",do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false) | ||||
| 4074 | &RMWI, ElTy)do { if (!(ElTy->isIntegerTy())) { CheckFailed("atomicrmw " + AtomicRMWInst::getOperationName(Op) + " operand must have integer type!" , &RMWI, ElTy); return; } } while (false); | ||||
| 4075 | } | ||||
| 4076 | checkAtomicMemAccessSize(ElTy, &RMWI); | ||||
| 4077 | Check(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP,do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false) | ||||
| 4078 | "Invalid binary operation!", &RMWI)do { if (!(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP)) { CheckFailed("Invalid binary operation!" , &RMWI); return; } } while (false); | ||||
| 4079 | visitInstruction(RMWI); | ||||
| 4080 | } | ||||
| 4081 | |||||
| 4082 | void Verifier::visitFenceInst(FenceInst &FI) { | ||||
| 4083 | const AtomicOrdering Ordering = FI.getOrdering(); | ||||
| 4084 | Check(Ordering == AtomicOrdering::Acquire ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4085 | Ordering == AtomicOrdering::Release ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4086 | Ordering == AtomicOrdering::AcquireRelease ||do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4087 | Ordering == AtomicOrdering::SequentiallyConsistent,do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4088 | "fence instructions may only have acquire, release, acq_rel, or "do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4089 | "seq_cst ordering.",do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false) | ||||
| 4090 | &FI)do { if (!(Ordering == AtomicOrdering::Acquire || Ordering == AtomicOrdering::Release || Ordering == AtomicOrdering::AcquireRelease || Ordering == AtomicOrdering::SequentiallyConsistent)) { CheckFailed ("fence instructions may only have acquire, release, acq_rel, or " "seq_cst ordering.", &FI); return; } } while (false); | ||||
| 4091 | visitInstruction(FI); | ||||
| 4092 | } | ||||
| 4093 | |||||
| 4094 | void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { | ||||
| 4095 | Check(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
| 4096 | EVI.getIndices()) == EVI.getType(),do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false) | ||||
| 4097 | "Invalid ExtractValueInst operands!", &EVI)do { if (!(ExtractValueInst::getIndexedType(EVI.getAggregateOperand ()->getType(), EVI.getIndices()) == EVI.getType())) { CheckFailed ("Invalid ExtractValueInst operands!", &EVI); return; } } while (false); | ||||
| 4098 | |||||
| 4099 | visitInstruction(EVI); | ||||
| 4100 | } | ||||
| 4101 | |||||
| 4102 | void Verifier::visitInsertValueInst(InsertValueInst &IVI) { | ||||
| 4103 | Check(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 4104 | IVI.getIndices()) ==do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 4105 | IVI.getOperand(1)->getType(),do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false) | ||||
| 4106 | "Invalid InsertValueInst operands!", &IVI)do { if (!(ExtractValueInst::getIndexedType(IVI.getAggregateOperand ()->getType(), IVI.getIndices()) == IVI.getOperand(1)-> getType())) { CheckFailed("Invalid InsertValueInst operands!" , &IVI); return; } } while (false); | ||||
| 4107 | |||||
| 4108 | visitInstruction(IVI); | ||||
| 4109 | } | ||||
| 4110 | |||||
| 4111 | static Value *getParentPad(Value *EHPad) { | ||||
| 4112 | if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad)) | ||||
| 4113 | return FPI->getParentPad(); | ||||
| 4114 | |||||
| 4115 | return cast<CatchSwitchInst>(EHPad)->getParentPad(); | ||||
| 4116 | } | ||||
| 4117 | |||||
| 4118 | void Verifier::visitEHPadPredecessors(Instruction &I) { | ||||
| 4119 | assert(I.isEHPad())(static_cast <bool> (I.isEHPad()) ? void (0) : __assert_fail ("I.isEHPad()", "llvm/lib/IR/Verifier.cpp", 4119, __extension__ __PRETTY_FUNCTION__)); | ||||
| 4120 | |||||
| 4121 | BasicBlock *BB = I.getParent(); | ||||
| 4122 | Function *F = BB->getParent(); | ||||
| 4123 | |||||
| 4124 | Check(BB != &F->getEntryBlock(), "EH pad cannot be in entry block.", &I)do { if (!(BB != &F->getEntryBlock())) { CheckFailed("EH pad cannot be in entry block." , &I); return; } } while (false); | ||||
| 4125 | |||||
| 4126 | if (auto *LPI = dyn_cast<LandingPadInst>(&I)) { | ||||
| 4127 | // The landingpad instruction defines its parent as a landing pad block. The | ||||
| 4128 | // landing pad block may be branched to only by the unwind edge of an | ||||
| 4129 | // invoke. | ||||
| 4130 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
| 4131 | const auto *II = dyn_cast<InvokeInst>(PredBB->getTerminator()); | ||||
| 4132 | Check(II && II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 4133 | "Block containing LandingPadInst must be jumped to "do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 4134 | "only by the unwind edge of an invoke.",do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false) | ||||
| 4135 | LPI)do { if (!(II && II->getUnwindDest() == BB && II->getNormalDest() != BB)) { CheckFailed("Block containing LandingPadInst must be jumped to " "only by the unwind edge of an invoke.", LPI); return; } } while (false); | ||||
| 4136 | } | ||||
| 4137 | return; | ||||
| 4138 | } | ||||
| 4139 | if (auto *CPI = dyn_cast<CatchPadInst>(&I)) { | ||||
| 4140 | if (!pred_empty(BB)) | ||||
| 4141 | Check(BB->getUniquePredecessor() == CPI->getCatchSwitch()->getParent(),do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 4142 | "Block containg CatchPadInst must be jumped to "do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 4143 | "only by its catchswitch.",do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false) | ||||
| 4144 | CPI)do { if (!(BB->getUniquePredecessor() == CPI->getCatchSwitch ()->getParent())) { CheckFailed("Block containg CatchPadInst must be jumped to " "only by its catchswitch.", CPI); return; } } while (false); | ||||
| 4145 | Check(BB != CPI->getCatchSwitch()->getUnwindDest(),do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
| 4146 | "Catchswitch cannot unwind to one of its catchpads",do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false) | ||||
| 4147 | CPI->getCatchSwitch(), CPI)do { if (!(BB != CPI->getCatchSwitch()->getUnwindDest() )) { CheckFailed("Catchswitch cannot unwind to one of its catchpads" , CPI->getCatchSwitch(), CPI); return; } } while (false); | ||||
| 4148 | return; | ||||
| 4149 | } | ||||
| 4150 | |||||
| 4151 | // Verify that each pred has a legal terminator with a legal to/from EH | ||||
| 4152 | // pad relationship. | ||||
| 4153 | Instruction *ToPad = &I; | ||||
| 4154 | Value *ToPadParent = getParentPad(ToPad); | ||||
| 4155 | for (BasicBlock *PredBB : predecessors(BB)) { | ||||
| 4156 | Instruction *TI = PredBB->getTerminator(); | ||||
| 4157 | Value *FromPad; | ||||
| 4158 | if (auto *II = dyn_cast<InvokeInst>(TI)) { | ||||
| 4159 | Check(II->getUnwindDest() == BB && II->getNormalDest() != BB,do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false) | ||||
| 4160 | "EH pad must be jumped to via an unwind edge", ToPad, II)do { if (!(II->getUnwindDest() == BB && II->getNormalDest () != BB)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, II); return; } } while (false); | ||||
| 4161 | if (auto Bundle = II->getOperandBundle(LLVMContext::OB_funclet)) | ||||
| 4162 | FromPad = Bundle->Inputs[0]; | ||||
| 4163 | else | ||||
| 4164 | FromPad = ConstantTokenNone::get(II->getContext()); | ||||
| 4165 | } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) { | ||||
| 4166 | FromPad = CRI->getOperand(0); | ||||
| 4167 | Check(FromPad != ToPadParent, "A cleanupret must exit its cleanup", CRI)do { if (!(FromPad != ToPadParent)) { CheckFailed("A cleanupret must exit its cleanup" , CRI); return; } } while (false); | ||||
| 4168 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) { | ||||
| 4169 | FromPad = CSI; | ||||
| 4170 | } else { | ||||
| 4171 | Check(false, "EH pad must be jumped to via an unwind edge", ToPad, TI)do { if (!(false)) { CheckFailed("EH pad must be jumped to via an unwind edge" , ToPad, TI); return; } } while (false); | ||||
| 4172 | } | ||||
| 4173 | |||||
| 4174 | // The edge may exit from zero or more nested pads. | ||||
| 4175 | SmallSet<Value *, 8> Seen; | ||||
| 4176 | for (;; FromPad = getParentPad(FromPad)) { | ||||
| 4177 | Check(FromPad != ToPad,do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false) | ||||
| 4178 | "EH pad cannot handle exceptions raised within it", FromPad, TI)do { if (!(FromPad != ToPad)) { CheckFailed("EH pad cannot handle exceptions raised within it" , FromPad, TI); return; } } while (false); | ||||
| 4179 | if (FromPad == ToPadParent) { | ||||
| 4180 | // This is a legal unwind edge. | ||||
| 4181 | break; | ||||
| 4182 | } | ||||
| 4183 | Check(!isa<ConstantTokenNone>(FromPad),do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false) | ||||
| 4184 | "A single unwind edge may only enter one EH pad", TI)do { if (!(!isa<ConstantTokenNone>(FromPad))) { CheckFailed ("A single unwind edge may only enter one EH pad", TI); return ; } } while (false); | ||||
| 4185 | Check(Seen.insert(FromPad).second, "EH pad jumps through a cycle of pads",do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false) | ||||
| 4186 | FromPad)do { if (!(Seen.insert(FromPad).second)) { CheckFailed("EH pad jumps through a cycle of pads" , FromPad); return; } } while (false); | ||||
| 4187 | |||||
| 4188 | // This will be diagnosed on the corresponding instruction already. We | ||||
| 4189 | // need the extra check here to make sure getParentPad() works. | ||||
| 4190 | Check(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst>(FromPad),do { if (!(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst >(FromPad))) { CheckFailed("Parent pad must be catchpad/cleanuppad/catchswitch" , TI); return; } } while (false) | ||||
| 4191 | "Parent pad must be catchpad/cleanuppad/catchswitch", TI)do { if (!(isa<FuncletPadInst>(FromPad) || isa<CatchSwitchInst >(FromPad))) { CheckFailed("Parent pad must be catchpad/cleanuppad/catchswitch" , TI); return; } } while (false); | ||||
| 4192 | } | ||||
| 4193 | } | ||||
| 4194 | } | ||||
| 4195 | |||||
| 4196 | void Verifier::visitLandingPadInst(LandingPadInst &LPI) { | ||||
| 4197 | // The landingpad instruction is ill-formed if it doesn't have any clauses and | ||||
| 4198 | // isn't a cleanup. | ||||
| 4199 | Check(LPI.getNumClauses() > 0 || LPI.isCleanup(),do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false) | ||||
| 4200 | "LandingPadInst needs at least one clause or to be a cleanup.", &LPI)do { if (!(LPI.getNumClauses() > 0 || LPI.isCleanup())) { CheckFailed ("LandingPadInst needs at least one clause or to be a cleanup." , &LPI); return; } } while (false); | ||||
| 4201 | |||||
| 4202 | visitEHPadPredecessors(LPI); | ||||
| 4203 | |||||
| 4204 | if (!LandingPadResultTy) | ||||
| 4205 | LandingPadResultTy = LPI.getType(); | ||||
| 4206 | else | ||||
| 4207 | Check(LandingPadResultTy == LPI.getType(),do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 4208 | "The landingpad instruction should have a consistent result type "do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 4209 | "inside a function.",do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false) | ||||
| 4210 | &LPI)do { if (!(LandingPadResultTy == LPI.getType())) { CheckFailed ("The landingpad instruction should have a consistent result type " "inside a function.", &LPI); return; } } while (false); | ||||
| 4211 | |||||
| 4212 | Function *F = LPI.getParent()->getParent(); | ||||
| 4213 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false) | ||||
| 4214 | "LandingPadInst needs to be in a function with a personality.", &LPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("LandingPadInst needs to be in a function with a personality." , &LPI); return; } } while (false); | ||||
| 4215 | |||||
| 4216 | // The landingpad instruction must be the first non-PHI instruction in the | ||||
| 4217 | // block. | ||||
| 4218 | Check(LPI.getParent()->getLandingPadInst() == &LPI,do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false) | ||||
| 4219 | "LandingPadInst not the first non-PHI instruction in the block.", &LPI)do { if (!(LPI.getParent()->getLandingPadInst() == &LPI )) { CheckFailed("LandingPadInst not the first non-PHI instruction in the block." , &LPI); return; } } while (false); | ||||
| 4220 | |||||
| 4221 | for (unsigned i = 0, e = LPI.getNumClauses(); i < e; ++i) { | ||||
| 4222 | Constant *Clause = LPI.getClause(i); | ||||
| 4223 | if (LPI.isCatch(i)) { | ||||
| 4224 | Check(isa<PointerType>(Clause->getType()),do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false) | ||||
| 4225 | "Catch operand does not have pointer type!", &LPI)do { if (!(isa<PointerType>(Clause->getType()))) { CheckFailed ("Catch operand does not have pointer type!", &LPI); return ; } } while (false); | ||||
| 4226 | } else { | ||||
| 4227 | Check(LPI.isFilter(i), "Clause is neither catch nor filter!", &LPI)do { if (!(LPI.isFilter(i))) { CheckFailed("Clause is neither catch nor filter!" , &LPI); return; } } while (false); | ||||
| 4228 | Check(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero>(Clause),do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false) | ||||
| 4229 | "Filter operand is not an array of constants!", &LPI)do { if (!(isa<ConstantArray>(Clause) || isa<ConstantAggregateZero >(Clause))) { CheckFailed("Filter operand is not an array of constants!" , &LPI); return; } } while (false); | ||||
| 4230 | } | ||||
| 4231 | } | ||||
| 4232 | |||||
| 4233 | visitInstruction(LPI); | ||||
| 4234 | } | ||||
| 4235 | |||||
| 4236 | void Verifier::visitResumeInst(ResumeInst &RI) { | ||||
| 4237 | Check(RI.getFunction()->hasPersonalityFn(),do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false) | ||||
| 4238 | "ResumeInst needs to be in a function with a personality.", &RI)do { if (!(RI.getFunction()->hasPersonalityFn())) { CheckFailed ("ResumeInst needs to be in a function with a personality.", & RI); return; } } while (false); | ||||
| 4239 | |||||
| 4240 | if (!LandingPadResultTy) | ||||
| 4241 | LandingPadResultTy = RI.getValue()->getType(); | ||||
| 4242 | else | ||||
| 4243 | Check(LandingPadResultTy == RI.getValue()->getType(),do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 4244 | "The resume instruction should have a consistent result type "do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 4245 | "inside a function.",do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false) | ||||
| 4246 | &RI)do { if (!(LandingPadResultTy == RI.getValue()->getType()) ) { CheckFailed("The resume instruction should have a consistent result type " "inside a function.", &RI); return; } } while (false); | ||||
| 4247 | |||||
| 4248 | visitTerminator(RI); | ||||
| 4249 | } | ||||
| 4250 | |||||
| 4251 | void Verifier::visitCatchPadInst(CatchPadInst &CPI) { | ||||
| 4252 | BasicBlock *BB = CPI.getParent(); | ||||
| 4253 | |||||
| 4254 | Function *F = BB->getParent(); | ||||
| 4255 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
| 4256 | "CatchPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
| 4257 | |||||
| 4258 | Check(isa<CatchSwitchInst>(CPI.getParentPad()),do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
| 4259 | "CatchPadInst needs to be directly nested in a CatchSwitchInst.",do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false) | ||||
| 4260 | CPI.getParentPad())do { if (!(isa<CatchSwitchInst>(CPI.getParentPad()))) { CheckFailed("CatchPadInst needs to be directly nested in a CatchSwitchInst." , CPI.getParentPad()); return; } } while (false); | ||||
| 4261 | |||||
| 4262 | // The catchpad instruction must be the first non-PHI instruction in the | ||||
| 4263 | // block. | ||||
| 4264 | Check(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
| 4265 | "CatchPadInst not the first non-PHI instruction in the block.", &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CatchPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
| 4266 | |||||
| 4267 | visitEHPadPredecessors(CPI); | ||||
| 4268 | visitFuncletPadInst(CPI); | ||||
| 4269 | } | ||||
| 4270 | |||||
| 4271 | void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) { | ||||
| 4272 | Check(isa<CatchPadInst>(CatchReturn.getOperand(0)),do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
| 4273 | "CatchReturnInst needs to be provided a CatchPad", &CatchReturn,do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false) | ||||
| 4274 | CatchReturn.getOperand(0))do { if (!(isa<CatchPadInst>(CatchReturn.getOperand(0)) )) { CheckFailed("CatchReturnInst needs to be provided a CatchPad" , &CatchReturn, CatchReturn.getOperand(0)); return; } } while (false); | ||||
| 4275 | |||||
| 4276 | visitTerminator(CatchReturn); | ||||
| 4277 | } | ||||
| 4278 | |||||
| 4279 | void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) { | ||||
| 4280 | BasicBlock *BB = CPI.getParent(); | ||||
| 4281 | |||||
| 4282 | Function *F = BB->getParent(); | ||||
| 4283 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false) | ||||
| 4284 | "CleanupPadInst needs to be in a function with a personality.", &CPI)do { if (!(F->hasPersonalityFn())) { CheckFailed("CleanupPadInst needs to be in a function with a personality." , &CPI); return; } } while (false); | ||||
| 4285 | |||||
| 4286 | // The cleanuppad instruction must be the first non-PHI instruction in the | ||||
| 4287 | // block. | ||||
| 4288 | Check(BB->getFirstNonPHI() == &CPI,do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false) | ||||
| 4289 | "CleanupPadInst not the first non-PHI instruction in the block.", &CPI)do { if (!(BB->getFirstNonPHI() == &CPI)) { CheckFailed ("CleanupPadInst not the first non-PHI instruction in the block." , &CPI); return; } } while (false); | ||||
| 4290 | |||||
| 4291 | auto *ParentPad = CPI.getParentPad(); | ||||
| 4292 | Check(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false) | ||||
| 4293 | "CleanupPadInst has an invalid parent.", &CPI)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CleanupPadInst has an invalid parent." , &CPI); return; } } while (false); | ||||
| 4294 | |||||
| 4295 | visitEHPadPredecessors(CPI); | ||||
| 4296 | visitFuncletPadInst(CPI); | ||||
| 4297 | } | ||||
| 4298 | |||||
| 4299 | void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { | ||||
| 4300 | User *FirstUser = nullptr; | ||||
| 4301 | Value *FirstUnwindPad = nullptr; | ||||
| 4302 | SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); | ||||
| 4303 | SmallSet<FuncletPadInst *, 8> Seen; | ||||
| 4304 | |||||
| 4305 | while (!Worklist.empty()) { | ||||
| 4306 | FuncletPadInst *CurrentPad = Worklist.pop_back_val(); | ||||
| 4307 | Check(Seen.insert(CurrentPad).second,do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false) | ||||
| 4308 | "FuncletPadInst must not be nested within itself", CurrentPad)do { if (!(Seen.insert(CurrentPad).second)) { CheckFailed("FuncletPadInst must not be nested within itself" , CurrentPad); return; } } while (false); | ||||
| 4309 | Value *UnresolvedAncestorPad = nullptr; | ||||
| 4310 | for (User *U : CurrentPad->users()) { | ||||
| 4311 | BasicBlock *UnwindDest; | ||||
| 4312 | if (auto *CRI = dyn_cast<CleanupReturnInst>(U)) { | ||||
| 4313 | UnwindDest = CRI->getUnwindDest(); | ||||
| 4314 | } else if (auto *CSI = dyn_cast<CatchSwitchInst>(U)) { | ||||
| 4315 | // We allow catchswitch unwind to caller to nest | ||||
| 4316 | // within an outer pad that unwinds somewhere else, | ||||
| 4317 | // because catchswitch doesn't have a nounwind variant. | ||||
| 4318 | // See e.g. SimplifyCFGOpt::SimplifyUnreachable. | ||||
| 4319 | if (CSI->unwindsToCaller()) | ||||
| 4320 | continue; | ||||
| 4321 | UnwindDest = CSI->getUnwindDest(); | ||||
| 4322 | } else if (auto *II = dyn_cast<InvokeInst>(U)) { | ||||
| 4323 | UnwindDest = II->getUnwindDest(); | ||||
| 4324 | } else if (isa<CallInst>(U)) { | ||||
| 4325 | // Calls which don't unwind may be found inside funclet | ||||
| 4326 | // pads that unwind somewhere else. We don't *require* | ||||
| 4327 | // such calls to be annotated nounwind. | ||||
| 4328 | continue; | ||||
| 4329 | } else if (auto *CPI = dyn_cast<CleanupPadInst>(U)) { | ||||
| 4330 | // The unwind dest for a cleanup can only be found by | ||||
| 4331 | // recursive search. Add it to the worklist, and we'll | ||||
| 4332 | // search for its first use that determines where it unwinds. | ||||
| 4333 | Worklist.push_back(CPI); | ||||
| 4334 | continue; | ||||
| 4335 | } else { | ||||
| 4336 | Check(isa<CatchReturnInst>(U), "Bogus funclet pad use", U)do { if (!(isa<CatchReturnInst>(U))) { CheckFailed("Bogus funclet pad use" , U); return; } } while (false); | ||||
| 4337 | continue; | ||||
| 4338 | } | ||||
| 4339 | |||||
| 4340 | Value *UnwindPad; | ||||
| 4341 | bool ExitsFPI; | ||||
| 4342 | if (UnwindDest) { | ||||
| 4343 | UnwindPad = UnwindDest->getFirstNonPHI(); | ||||
| 4344 | if (!cast<Instruction>(UnwindPad)->isEHPad()) | ||||
| 4345 | continue; | ||||
| 4346 | Value *UnwindParent = getParentPad(UnwindPad); | ||||
| 4347 | // Ignore unwind edges that don't exit CurrentPad. | ||||
| 4348 | if (UnwindParent == CurrentPad) | ||||
| 4349 | continue; | ||||
| 4350 | // Determine whether the original funclet pad is exited, | ||||
| 4351 | // and if we are scanning nested pads determine how many | ||||
| 4352 | // of them are exited so we can stop searching their | ||||
| 4353 | // children. | ||||
| 4354 | Value *ExitedPad = CurrentPad; | ||||
| 4355 | ExitsFPI = false; | ||||
| 4356 | do { | ||||
| 4357 | if (ExitedPad == &FPI) { | ||||
| 4358 | ExitsFPI = true; | ||||
| 4359 | // Now we can resolve any ancestors of CurrentPad up to | ||||
| 4360 | // FPI, but not including FPI since we need to make sure | ||||
| 4361 | // to check all direct users of FPI for consistency. | ||||
| 4362 | UnresolvedAncestorPad = &FPI; | ||||
| 4363 | break; | ||||
| 4364 | } | ||||
| 4365 | Value *ExitedParent = getParentPad(ExitedPad); | ||||
| 4366 | if (ExitedParent == UnwindParent) { | ||||
| 4367 | // ExitedPad is the ancestor-most pad which this unwind | ||||
| 4368 | // edge exits, so we can resolve up to it, meaning that | ||||
| 4369 | // ExitedParent is the first ancestor still unresolved. | ||||
| 4370 | UnresolvedAncestorPad = ExitedParent; | ||||
| 4371 | break; | ||||
| 4372 | } | ||||
| 4373 | ExitedPad = ExitedParent; | ||||
| 4374 | } while (!isa<ConstantTokenNone>(ExitedPad)); | ||||
| 4375 | } else { | ||||
| 4376 | // Unwinding to caller exits all pads. | ||||
| 4377 | UnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
| 4378 | ExitsFPI = true; | ||||
| 4379 | UnresolvedAncestorPad = &FPI; | ||||
| 4380 | } | ||||
| 4381 | |||||
| 4382 | if (ExitsFPI) { | ||||
| 4383 | // This unwind edge exits FPI. Make sure it agrees with other | ||||
| 4384 | // such edges. | ||||
| 4385 | if (FirstUser) { | ||||
| 4386 | Check(UnwindPad == FirstUnwindPad,do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4387 | "Unwind edges out of a funclet "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4388 | "pad must have the same unwind "do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4389 | "dest",do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false) | ||||
| 4390 | &FPI, U, FirstUser)do { if (!(UnwindPad == FirstUnwindPad)) { CheckFailed("Unwind edges out of a funclet " "pad must have the same unwind " "dest", &FPI, U, FirstUser ); return; } } while (false); | ||||
| 4391 | } else { | ||||
| 4392 | FirstUser = U; | ||||
| 4393 | FirstUnwindPad = UnwindPad; | ||||
| 4394 | // Record cleanup sibling unwinds for verifySiblingFuncletUnwinds | ||||
| 4395 | if (isa<CleanupPadInst>(&FPI) && !isa<ConstantTokenNone>(UnwindPad) && | ||||
| 4396 | getParentPad(UnwindPad) == getParentPad(&FPI)) | ||||
| 4397 | SiblingFuncletInfo[&FPI] = cast<Instruction>(U); | ||||
| 4398 | } | ||||
| 4399 | } | ||||
| 4400 | // Make sure we visit all uses of FPI, but for nested pads stop as | ||||
| 4401 | // soon as we know where they unwind to. | ||||
| 4402 | if (CurrentPad != &FPI) | ||||
| 4403 | break; | ||||
| 4404 | } | ||||
| 4405 | if (UnresolvedAncestorPad) { | ||||
| 4406 | if (CurrentPad == UnresolvedAncestorPad) { | ||||
| 4407 | // When CurrentPad is FPI itself, we don't mark it as resolved even if | ||||
| 4408 | // we've found an unwind edge that exits it, because we need to verify | ||||
| 4409 | // all direct uses of FPI. | ||||
| 4410 | assert(CurrentPad == &FPI)(static_cast <bool> (CurrentPad == &FPI) ? void (0) : __assert_fail ("CurrentPad == &FPI", "llvm/lib/IR/Verifier.cpp" , 4410, __extension__ __PRETTY_FUNCTION__)); | ||||
| 4411 | continue; | ||||
| 4412 | } | ||||
| 4413 | // Pop off the worklist any nested pads that we've found an unwind | ||||
| 4414 | // destination for. The pads on the worklist are the uncles, | ||||
| 4415 | // great-uncles, etc. of CurrentPad. We've found an unwind destination | ||||
| 4416 | // for all ancestors of CurrentPad up to but not including | ||||
| 4417 | // UnresolvedAncestorPad. | ||||
| 4418 | Value *ResolvedPad = CurrentPad; | ||||
| 4419 | while (!Worklist.empty()) { | ||||
| 4420 | Value *UnclePad = Worklist.back(); | ||||
| 4421 | Value *AncestorPad = getParentPad(UnclePad); | ||||
| 4422 | // Walk ResolvedPad up the ancestor list until we either find the | ||||
| 4423 | // uncle's parent or the last resolved ancestor. | ||||
| 4424 | while (ResolvedPad != AncestorPad) { | ||||
| 4425 | Value *ResolvedParent = getParentPad(ResolvedPad); | ||||
| 4426 | if (ResolvedParent == UnresolvedAncestorPad) { | ||||
| 4427 | break; | ||||
| 4428 | } | ||||
| 4429 | ResolvedPad = ResolvedParent; | ||||
| 4430 | } | ||||
| 4431 | // If the resolved ancestor search didn't find the uncle's parent, | ||||
| 4432 | // then the uncle is not yet resolved. | ||||
| 4433 | if (ResolvedPad != AncestorPad) | ||||
| 4434 | break; | ||||
| 4435 | // This uncle is resolved, so pop it from the worklist. | ||||
| 4436 | Worklist.pop_back(); | ||||
| 4437 | } | ||||
| 4438 | } | ||||
| 4439 | } | ||||
| 4440 | |||||
| 4441 | if (FirstUnwindPad) { | ||||
| 4442 | if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(FPI.getParentPad())) { | ||||
| 4443 | BasicBlock *SwitchUnwindDest = CatchSwitch->getUnwindDest(); | ||||
| 4444 | Value *SwitchUnwindPad; | ||||
| 4445 | if (SwitchUnwindDest) | ||||
| 4446 | SwitchUnwindPad = SwitchUnwindDest->getFirstNonPHI(); | ||||
| 4447 | else | ||||
| 4448 | SwitchUnwindPad = ConstantTokenNone::get(FPI.getContext()); | ||||
| 4449 | Check(SwitchUnwindPad == FirstUnwindPad,do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4450 | "Unwind edges out of a catch must have the same unwind dest as "do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4451 | "the parent catchswitch",do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false) | ||||
| 4452 | &FPI, FirstUser, CatchSwitch)do { if (!(SwitchUnwindPad == FirstUnwindPad)) { CheckFailed( "Unwind edges out of a catch must have the same unwind dest as " "the parent catchswitch", &FPI, FirstUser, CatchSwitch); return; } } while (false); | ||||
| 4453 | } | ||||
| 4454 | } | ||||
| 4455 | |||||
| 4456 | visitInstruction(FPI); | ||||
| 4457 | } | ||||
| 4458 | |||||
| 4459 | void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) { | ||||
| 4460 | BasicBlock *BB = CatchSwitch.getParent(); | ||||
| 4461 | |||||
| 4462 | Function *F = BB->getParent(); | ||||
| 4463 | Check(F->hasPersonalityFn(),do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
| 4464 | "CatchSwitchInst needs to be in a function with a personality.",do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false) | ||||
| 4465 | &CatchSwitch)do { if (!(F->hasPersonalityFn())) { CheckFailed("CatchSwitchInst needs to be in a function with a personality." , &CatchSwitch); return; } } while (false); | ||||
| 4466 | |||||
| 4467 | // The catchswitch instruction must be the first non-PHI instruction in the | ||||
| 4468 | // block. | ||||
| 4469 | Check(BB->getFirstNonPHI() == &CatchSwitch,do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
| 4470 | "CatchSwitchInst not the first non-PHI instruction in the block.",do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false) | ||||
| 4471 | &CatchSwitch)do { if (!(BB->getFirstNonPHI() == &CatchSwitch)) { CheckFailed ("CatchSwitchInst not the first non-PHI instruction in the block." , &CatchSwitch); return; } } while (false); | ||||
| 4472 | |||||
| 4473 | auto *ParentPad = CatchSwitch.getParentPad(); | ||||
| 4474 | Check(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false) | ||||
| 4475 | "CatchSwitchInst has an invalid parent.", ParentPad)do { if (!(isa<ConstantTokenNone>(ParentPad) || isa< FuncletPadInst>(ParentPad))) { CheckFailed("CatchSwitchInst has an invalid parent." , ParentPad); return; } } while (false); | ||||
| 4476 | |||||
| 4477 | if (BasicBlock *UnwindDest = CatchSwitch.getUnwindDest()) { | ||||
| 4478 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
| 4479 | Check(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4480 | "CatchSwitchInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4481 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false) | ||||
| 4482 | &CatchSwitch)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CatchSwitchInst must unwind to an EH block which is not a " "landingpad.", &CatchSwitch); return; } } while (false); | ||||
| 4483 | |||||
| 4484 | // Record catchswitch sibling unwinds for verifySiblingFuncletUnwinds | ||||
| 4485 | if (getParentPad(I) == ParentPad) | ||||
| 4486 | SiblingFuncletInfo[&CatchSwitch] = &CatchSwitch; | ||||
| 4487 | } | ||||
| 4488 | |||||
| 4489 | Check(CatchSwitch.getNumHandlers() != 0,do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false) | ||||
| 4490 | "CatchSwitchInst cannot have empty handler list", &CatchSwitch)do { if (!(CatchSwitch.getNumHandlers() != 0)) { CheckFailed( "CatchSwitchInst cannot have empty handler list", &CatchSwitch ); return; } } while (false); | ||||
| 4491 | |||||
| 4492 | for (BasicBlock *Handler : CatchSwitch.handlers()) { | ||||
| 4493 | Check(isa<CatchPadInst>(Handler->getFirstNonPHI()),do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false) | ||||
| 4494 | "CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler)do { if (!(isa<CatchPadInst>(Handler->getFirstNonPHI ()))) { CheckFailed("CatchSwitchInst handlers must be catchpads" , &CatchSwitch, Handler); return; } } while (false); | ||||
| 4495 | } | ||||
| 4496 | |||||
| 4497 | visitEHPadPredecessors(CatchSwitch); | ||||
| 4498 | visitTerminator(CatchSwitch); | ||||
| 4499 | } | ||||
| 4500 | |||||
| 4501 | void Verifier::visitCleanupReturnInst(CleanupReturnInst &CRI) { | ||||
| 4502 | Check(isa<CleanupPadInst>(CRI.getOperand(0)),do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
| 4503 | "CleanupReturnInst needs to be provided a CleanupPad", &CRI,do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false) | ||||
| 4504 | CRI.getOperand(0))do { if (!(isa<CleanupPadInst>(CRI.getOperand(0)))) { CheckFailed ("CleanupReturnInst needs to be provided a CleanupPad", & CRI, CRI.getOperand(0)); return; } } while (false); | ||||
| 4505 | |||||
| 4506 | if (BasicBlock *UnwindDest = CRI.getUnwindDest()) { | ||||
| 4507 | Instruction *I = UnwindDest->getFirstNonPHI(); | ||||
| 4508 | Check(I->isEHPad() && !isa<LandingPadInst>(I),do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4509 | "CleanupReturnInst must unwind to an EH block which is not a "do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4510 | "landingpad.",do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false) | ||||
| 4511 | &CRI)do { if (!(I->isEHPad() && !isa<LandingPadInst> (I))) { CheckFailed("CleanupReturnInst must unwind to an EH block which is not a " "landingpad.", &CRI); return; } } while (false); | ||||
| 4512 | } | ||||
| 4513 | |||||
| 4514 | visitTerminator(CRI); | ||||
| 4515 | } | ||||
| 4516 | |||||
| 4517 | void Verifier::verifyDominatesUse(Instruction &I, unsigned i) { | ||||
| 4518 | Instruction *Op = cast<Instruction>(I.getOperand(i)); | ||||
| 4519 | // If the we have an invalid invoke, don't try to compute the dominance. | ||||
| 4520 | // We already reject it in the invoke specific checks and the dominance | ||||
| 4521 | // computation doesn't handle multiple edges. | ||||
| 4522 | if (InvokeInst *II = dyn_cast<InvokeInst>(Op)) { | ||||
| 4523 | if (II->getNormalDest() == II->getUnwindDest()) | ||||
| 4524 | return; | ||||
| 4525 | } | ||||
| 4526 | |||||
| 4527 | // Quick check whether the def has already been encountered in the same block. | ||||
| 4528 | // PHI nodes are not checked to prevent accepting preceding PHIs, because PHI | ||||
| 4529 | // uses are defined to happen on the incoming edge, not at the instruction. | ||||
| 4530 | // | ||||
| 4531 | // FIXME: If this operand is a MetadataAsValue (wrapping a LocalAsMetadata) | ||||
| 4532 | // wrapping an SSA value, assert that we've already encountered it. See | ||||
| 4533 | // related FIXME in Mapper::mapLocalAsMetadata in ValueMapper.cpp. | ||||
| 4534 | if (!isa<PHINode>(I) && InstsInThisBlock.count(Op)) | ||||
| 4535 | return; | ||||
| 4536 | |||||
| 4537 | const Use &U = I.getOperandUse(i); | ||||
| 4538 | Check(DT.dominates(Op, U), "Instruction does not dominate all uses!", Op, &I)do { if (!(DT.dominates(Op, U))) { CheckFailed("Instruction does not dominate all uses!" , Op, &I); return; } } while (false); | ||||
| 4539 | } | ||||
| 4540 | |||||
| 4541 | void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { | ||||
| 4542 | Check(I.getType()->isPointerTy(),do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
| 4543 | "dereferenceable, dereferenceable_or_null "do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
| 4544 | "apply only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ) | ||||
| 4545 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("dereferenceable, dereferenceable_or_null " "apply only to pointer types", &I); return; } } while (false ); | ||||
| 4546 | Check((isa<LoadInst>(I) || isa<IntToPtrInst>(I)),do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
| 4547 | "dereferenceable, dereferenceable_or_null apply only to load"do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
| 4548 | " and inttoptr instructions, use attributes for calls or invokes",do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false) | ||||
| 4549 | &I)do { if (!((isa<LoadInst>(I) || isa<IntToPtrInst> (I)))) { CheckFailed("dereferenceable, dereferenceable_or_null apply only to load" " and inttoptr instructions, use attributes for calls or invokes" , &I); return; } } while (false); | ||||
| 4550 | Check(MD->getNumOperands() == 1,do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
| 4551 | "dereferenceable, dereferenceable_or_null "do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
| 4552 | "take one operand!",do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false) | ||||
| 4553 | &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("dereferenceable, dereferenceable_or_null " "take one operand!", &I); return; } } while (false); | ||||
| 4554 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)); | ||||
| 4555 | Check(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
| 4556 | "dereferenceable, "do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
| 4557 | "dereferenceable_or_null metadata value must be an i64!",do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false) | ||||
| 4558 | &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("dereferenceable, " "dereferenceable_or_null metadata value must be an i64!" , &I); return; } } while (false); | ||||
| 4559 | } | ||||
| 4560 | |||||
| 4561 | void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { | ||||
| 4562 | Check(MD->getNumOperands() >= 2,do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false) | ||||
| 4563 | "!prof annotations should have no less than 2 operands", MD)do { if (!(MD->getNumOperands() >= 2)) { CheckFailed("!prof annotations should have no less than 2 operands" , MD); return; } } while (false); | ||||
| 4564 | |||||
| 4565 | // Check first operand. | ||||
| 4566 | Check(MD->getOperand(0) != nullptr, "first operand should not be null", MD)do { if (!(MD->getOperand(0) != nullptr)) { CheckFailed("first operand should not be null" , MD); return; } } while (false); | ||||
| 4567 | Check(isa<MDString>(MD->getOperand(0)),do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false) | ||||
| 4568 | "expected string with name of the !prof annotation", MD)do { if (!(isa<MDString>(MD->getOperand(0)))) { CheckFailed ("expected string with name of the !prof annotation", MD); return ; } } while (false); | ||||
| 4569 | MDString *MDS = cast<MDString>(MD->getOperand(0)); | ||||
| 4570 | StringRef ProfName = MDS->getString(); | ||||
| 4571 | |||||
| 4572 | // Check consistency of !prof branch_weights metadata. | ||||
| 4573 | if (ProfName.equals("branch_weights")) { | ||||
| 4574 | if (isa<InvokeInst>(&I)) { | ||||
| 4575 | Check(MD->getNumOperands() == 2 || MD->getNumOperands() == 3,do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false) | ||||
| 4576 | "Wrong number of InvokeInst branch_weights operands", MD)do { if (!(MD->getNumOperands() == 2 || MD->getNumOperands () == 3)) { CheckFailed("Wrong number of InvokeInst branch_weights operands" , MD); return; } } while (false); | ||||
| 4577 | } else { | ||||
| 4578 | unsigned ExpectedNumOperands = 0; | ||||
| 4579 | if (BranchInst *BI = dyn_cast<BranchInst>(&I)) | ||||
| 4580 | ExpectedNumOperands = BI->getNumSuccessors(); | ||||
| 4581 | else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) | ||||
| 4582 | ExpectedNumOperands = SI->getNumSuccessors(); | ||||
| 4583 | else if (isa<CallInst>(&I)) | ||||
| 4584 | ExpectedNumOperands = 1; | ||||
| 4585 | else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(&I)) | ||||
| 4586 | ExpectedNumOperands = IBI->getNumDestinations(); | ||||
| 4587 | else if (isa<SelectInst>(&I)) | ||||
| 4588 | ExpectedNumOperands = 2; | ||||
| 4589 | else if (CallBrInst *CI = dyn_cast<CallBrInst>(&I)) | ||||
| 4590 | ExpectedNumOperands = CI->getNumSuccessors(); | ||||
| 4591 | else | ||||
| 4592 | CheckFailed("!prof branch_weights are not allowed for this instruction", | ||||
| 4593 | MD); | ||||
| 4594 | |||||
| 4595 | Check(MD->getNumOperands() == 1 + ExpectedNumOperands,do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false) | ||||
| 4596 | "Wrong number of operands", MD)do { if (!(MD->getNumOperands() == 1 + ExpectedNumOperands )) { CheckFailed("Wrong number of operands", MD); return; } } while (false); | ||||
| 4597 | } | ||||
| 4598 | for (unsigned i = 1; i < MD->getNumOperands(); ++i) { | ||||
| 4599 | auto &MDO = MD->getOperand(i); | ||||
| 4600 | Check(MDO, "second operand should not be null", MD)do { if (!(MDO)) { CheckFailed("second operand should not be null" , MD); return; } } while (false); | ||||
| 4601 | Check(mdconst::dyn_extract<ConstantInt>(MDO),do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false) | ||||
| 4602 | "!prof brunch_weights operand is not a const int")do { if (!(mdconst::dyn_extract<ConstantInt>(MDO))) { CheckFailed ("!prof brunch_weights operand is not a const int"); return; } } while (false); | ||||
| 4603 | } | ||||
| 4604 | } | ||||
| 4605 | } | ||||
| 4606 | |||||
| 4607 | void Verifier::visitDIAssignIDMetadata(Instruction &I, MDNode *MD) { | ||||
| 4608 | assert(I.hasMetadata(LLVMContext::MD_DIAssignID))(static_cast <bool> (I.hasMetadata(LLVMContext::MD_DIAssignID )) ? void (0) : __assert_fail ("I.hasMetadata(LLVMContext::MD_DIAssignID)" , "llvm/lib/IR/Verifier.cpp", 4608, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 4609 | bool ExpectedInstTy = | ||||
| 4610 | isa<AllocaInst>(I) || isa<StoreInst>(I) || isa<MemIntrinsic>(I); | ||||
| 4611 | CheckDI(ExpectedInstTy, "!DIAssignID attached to unexpected instruction kind",do { if (!(ExpectedInstTy)) { DebugInfoCheckFailed("!DIAssignID attached to unexpected instruction kind" , I, MD); return; } } while (false) | ||||
| 4612 | I, MD)do { if (!(ExpectedInstTy)) { DebugInfoCheckFailed("!DIAssignID attached to unexpected instruction kind" , I, MD); return; } } while (false); | ||||
| 4613 | // Iterate over the MetadataAsValue uses of the DIAssignID - these should | ||||
| 4614 | // only be found as DbgAssignIntrinsic operands. | ||||
| 4615 | if (auto *AsValue = MetadataAsValue::getIfExists(Context, MD)) { | ||||
| 4616 | for (auto *User : AsValue->users()) { | ||||
| 4617 | CheckDI(isa<DbgAssignIntrinsic>(User),do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false) | ||||
| 4618 | "!DIAssignID should only be used by llvm.dbg.assign intrinsics",do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false) | ||||
| 4619 | MD, User)do { if (!(isa<DbgAssignIntrinsic>(User))) { DebugInfoCheckFailed ("!DIAssignID should only be used by llvm.dbg.assign intrinsics" , MD, User); return; } } while (false); | ||||
| 4620 | // All of the dbg.assign intrinsics should be in the same function as I. | ||||
| 4621 | if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(User)) | ||||
| 4622 | CheckDI(DAI->getFunction() == I.getFunction(),do { if (!(DAI->getFunction() == I.getFunction())) { DebugInfoCheckFailed ("dbg.assign not in same function as inst", DAI, &I); return ; } } while (false) | ||||
| 4623 | "dbg.assign not in same function as inst", DAI, &I)do { if (!(DAI->getFunction() == I.getFunction())) { DebugInfoCheckFailed ("dbg.assign not in same function as inst", DAI, &I); return ; } } while (false); | ||||
| 4624 | } | ||||
| 4625 | } | ||||
| 4626 | } | ||||
| 4627 | |||||
| 4628 | void Verifier::visitCallStackMetadata(MDNode *MD) { | ||||
| 4629 | // Call stack metadata should consist of a list of at least 1 constant int | ||||
| 4630 | // (representing a hash of the location). | ||||
| 4631 | Check(MD->getNumOperands() >= 1,do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("call stack metadata should have at least 1 operand" , MD); return; } } while (false) | ||||
| 4632 | "call stack metadata should have at least 1 operand", MD)do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("call stack metadata should have at least 1 operand" , MD); return; } } while (false); | ||||
| 4633 | |||||
| 4634 | for (const auto &Op : MD->operands()) | ||||
| 4635 | Check(mdconst::dyn_extract_or_null<ConstantInt>(Op),do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ))) { CheckFailed("call stack metadata operand should be constant integer" , Op); return; } } while (false) | ||||
| 4636 | "call stack metadata operand should be constant integer", Op)do { if (!(mdconst::dyn_extract_or_null<ConstantInt>(Op ))) { CheckFailed("call stack metadata operand should be constant integer" , Op); return; } } while (false); | ||||
| 4637 | } | ||||
| 4638 | |||||
| 4639 | void Verifier::visitMemProfMetadata(Instruction &I, MDNode *MD) { | ||||
| 4640 | Check(isa<CallBase>(I), "!memprof metadata should only exist on calls", &I)do { if (!(isa<CallBase>(I))) { CheckFailed("!memprof metadata should only exist on calls" , &I); return; } } while (false); | ||||
| 4641 | Check(MD->getNumOperands() >= 1,do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
| 4642 | "!memprof annotations should have at least 1 metadata operand "do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
| 4643 | "(MemInfoBlock)",do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false) | ||||
| 4644 | MD)do { if (!(MD->getNumOperands() >= 1)) { CheckFailed("!memprof annotations should have at least 1 metadata operand " "(MemInfoBlock)", MD); return; } } while (false); | ||||
| 4645 | |||||
| 4646 | // Check each MIB | ||||
| 4647 | for (auto &MIBOp : MD->operands()) { | ||||
| 4648 | MDNode *MIB = dyn_cast<MDNode>(MIBOp); | ||||
| 4649 | // The first operand of an MIB should be the call stack metadata. | ||||
| 4650 | // There rest of the operands should be MDString tags, and there should be | ||||
| 4651 | // at least one. | ||||
| 4652 | Check(MIB->getNumOperands() >= 2,do { if (!(MIB->getNumOperands() >= 2)) { CheckFailed("Each !memprof MemInfoBlock should have at least 2 operands" , MIB); return; } } while (false) | ||||
| 4653 | "Each !memprof MemInfoBlock should have at least 2 operands", MIB)do { if (!(MIB->getNumOperands() >= 2)) { CheckFailed("Each !memprof MemInfoBlock should have at least 2 operands" , MIB); return; } } while (false); | ||||
| 4654 | |||||
| 4655 | // Check call stack metadata (first operand). | ||||
| 4656 | Check(MIB->getOperand(0) != nullptr,do { if (!(MIB->getOperand(0) != nullptr)) { CheckFailed("!memprof MemInfoBlock first operand should not be null" , MIB); return; } } while (false) | ||||
| 4657 | "!memprof MemInfoBlock first operand should not be null", MIB)do { if (!(MIB->getOperand(0) != nullptr)) { CheckFailed("!memprof MemInfoBlock first operand should not be null" , MIB); return; } } while (false); | ||||
| 4658 | Check(isa<MDNode>(MIB->getOperand(0)),do { if (!(isa<MDNode>(MIB->getOperand(0)))) { CheckFailed ("!memprof MemInfoBlock first operand should be an MDNode", MIB ); return; } } while (false) | ||||
| 4659 | "!memprof MemInfoBlock first operand should be an MDNode", MIB)do { if (!(isa<MDNode>(MIB->getOperand(0)))) { CheckFailed ("!memprof MemInfoBlock first operand should be an MDNode", MIB ); return; } } while (false); | ||||
| 4660 | MDNode *StackMD = dyn_cast<MDNode>(MIB->getOperand(0)); | ||||
| 4661 | visitCallStackMetadata(StackMD); | ||||
| 4662 | |||||
| 4663 | // Check that remaining operands are MDString. | ||||
| 4664 | Check(llvm::all_of(llvm::drop_begin(MIB->operands()),do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false) | ||||
| 4665 | [](const MDOperand &Op) { return isa<MDString>(Op); }),do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false) | ||||
| 4666 | "Not all !memprof MemInfoBlock operands 1 to N are MDString", MIB)do { if (!(llvm::all_of(llvm::drop_begin(MIB->operands()), [](const MDOperand &Op) { return isa<MDString>(Op) ; }))) { CheckFailed("Not all !memprof MemInfoBlock operands 1 to N are MDString" , MIB); return; } } while (false); | ||||
| 4667 | } | ||||
| 4668 | } | ||||
| 4669 | |||||
| 4670 | void Verifier::visitCallsiteMetadata(Instruction &I, MDNode *MD) { | ||||
| 4671 | Check(isa<CallBase>(I), "!callsite metadata should only exist on calls", &I)do { if (!(isa<CallBase>(I))) { CheckFailed("!callsite metadata should only exist on calls" , &I); return; } } while (false); | ||||
| 4672 | // Verify the partial callstack annotated from memprof profiles. This callsite | ||||
| 4673 | // is a part of a profiled allocation callstack. | ||||
| 4674 | visitCallStackMetadata(MD); | ||||
| 4675 | } | ||||
| 4676 | |||||
| 4677 | void Verifier::visitAnnotationMetadata(MDNode *Annotation) { | ||||
| 4678 | Check(isa<MDTuple>(Annotation), "annotation must be a tuple")do { if (!(isa<MDTuple>(Annotation))) { CheckFailed("annotation must be a tuple" ); return; } } while (false); | ||||
| 4679 | Check(Annotation->getNumOperands() >= 1,do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false) | ||||
| 4680 | "annotation must have at least one operand")do { if (!(Annotation->getNumOperands() >= 1)) { CheckFailed ("annotation must have at least one operand"); return; } } while (false); | ||||
| 4681 | for (const MDOperand &Op : Annotation->operands()) { | ||||
| 4682 | bool TupleOfStrings = | ||||
| 4683 | isa<MDTuple>(Op.get()) && | ||||
| 4684 | all_of(cast<MDTuple>(Op)->operands(), [](auto &Annotation) { | ||||
| 4685 | return isa<MDString>(Annotation.get()); | ||||
| 4686 | }); | ||||
| 4687 | Check(isa<MDString>(Op.get()) || TupleOfStrings,do { if (!(isa<MDString>(Op.get()) || TupleOfStrings)) { CheckFailed("operands must be a string or a tuple of strings" ); return; } } while (false) | ||||
| 4688 | "operands must be a string or a tuple of strings")do { if (!(isa<MDString>(Op.get()) || TupleOfStrings)) { CheckFailed("operands must be a string or a tuple of strings" ); return; } } while (false); | ||||
| 4689 | } | ||||
| 4690 | } | ||||
| 4691 | |||||
| 4692 | void Verifier::visitAliasScopeMetadata(const MDNode *MD) { | ||||
| 4693 | unsigned NumOps = MD->getNumOperands(); | ||||
| 4694 | Check(NumOps >= 2 && NumOps <= 3, "scope must have two or three operands",do { if (!(NumOps >= 2 && NumOps <= 3)) { CheckFailed ("scope must have two or three operands", MD); return; } } while (false) | ||||
| 4695 | MD)do { if (!(NumOps >= 2 && NumOps <= 3)) { CheckFailed ("scope must have two or three operands", MD); return; } } while (false); | ||||
| 4696 | Check(MD->getOperand(0).get() == MD || isa<MDString>(MD->getOperand(0)),do { if (!(MD->getOperand(0).get() == MD || isa<MDString >(MD->getOperand(0)))) { CheckFailed("first scope operand must be self-referential or string" , MD); return; } } while (false) | ||||
| 4697 | "first scope operand must be self-referential or string", MD)do { if (!(MD->getOperand(0).get() == MD || isa<MDString >(MD->getOperand(0)))) { CheckFailed("first scope operand must be self-referential or string" , MD); return; } } while (false); | ||||
| 4698 | if (NumOps == 3) | ||||
| 4699 | Check(isa<MDString>(MD->getOperand(2)),do { if (!(isa<MDString>(MD->getOperand(2)))) { CheckFailed ("third scope operand must be string (if used)", MD); return; } } while (false) | ||||
| 4700 | "third scope operand must be string (if used)", MD)do { if (!(isa<MDString>(MD->getOperand(2)))) { CheckFailed ("third scope operand must be string (if used)", MD); return; } } while (false); | ||||
| 4701 | |||||
| 4702 | MDNode *Domain = dyn_cast<MDNode>(MD->getOperand(1)); | ||||
| 4703 | Check(Domain != nullptr, "second scope operand must be MDNode", MD)do { if (!(Domain != nullptr)) { CheckFailed("second scope operand must be MDNode" , MD); return; } } while (false); | ||||
| 4704 | |||||
| 4705 | unsigned NumDomainOps = Domain->getNumOperands(); | ||||
| 4706 | Check(NumDomainOps >= 1 && NumDomainOps <= 2,do { if (!(NumDomainOps >= 1 && NumDomainOps <= 2)) { CheckFailed("domain must have one or two operands", Domain ); return; } } while (false) | ||||
| 4707 | "domain must have one or two operands", Domain)do { if (!(NumDomainOps >= 1 && NumDomainOps <= 2)) { CheckFailed("domain must have one or two operands", Domain ); return; } } while (false); | ||||
| 4708 | Check(Domain->getOperand(0).get() == Domain ||do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false) | ||||
| 4709 | isa<MDString>(Domain->getOperand(0)),do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false) | ||||
| 4710 | "first domain operand must be self-referential or string", Domain)do { if (!(Domain->getOperand(0).get() == Domain || isa< MDString>(Domain->getOperand(0)))) { CheckFailed("first domain operand must be self-referential or string" , Domain); return; } } while (false); | ||||
| 4711 | if (NumDomainOps == 2) | ||||
| 4712 | Check(isa<MDString>(Domain->getOperand(1)),do { if (!(isa<MDString>(Domain->getOperand(1)))) { CheckFailed ("second domain operand must be string (if used)", Domain); return ; } } while (false) | ||||
| 4713 | "second domain operand must be string (if used)", Domain)do { if (!(isa<MDString>(Domain->getOperand(1)))) { CheckFailed ("second domain operand must be string (if used)", Domain); return ; } } while (false); | ||||
| 4714 | } | ||||
| 4715 | |||||
| 4716 | void Verifier::visitAliasScopeListMetadata(const MDNode *MD) { | ||||
| 4717 | for (const MDOperand &Op : MD->operands()) { | ||||
| 4718 | const MDNode *OpMD = dyn_cast<MDNode>(Op); | ||||
| 4719 | Check(OpMD != nullptr, "scope list must consist of MDNodes", MD)do { if (!(OpMD != nullptr)) { CheckFailed("scope list must consist of MDNodes" , MD); return; } } while (false); | ||||
| 4720 | visitAliasScopeMetadata(OpMD); | ||||
| 4721 | } | ||||
| 4722 | } | ||||
| 4723 | |||||
| 4724 | void Verifier::visitAccessGroupMetadata(const MDNode *MD) { | ||||
| 4725 | auto IsValidAccessScope = [](const MDNode *MD) { | ||||
| 4726 | return MD->getNumOperands() == 0 && MD->isDistinct(); | ||||
| 4727 | }; | ||||
| 4728 | |||||
| 4729 | // It must be either an access scope itself... | ||||
| 4730 | if (IsValidAccessScope(MD)) | ||||
| 4731 | return; | ||||
| 4732 | |||||
| 4733 | // ...or a list of access scopes. | ||||
| 4734 | for (const MDOperand &Op : MD->operands()) { | ||||
| 4735 | const MDNode *OpMD = dyn_cast<MDNode>(Op); | ||||
| 4736 | Check(OpMD != nullptr, "Access scope list must consist of MDNodes", MD)do { if (!(OpMD != nullptr)) { CheckFailed("Access scope list must consist of MDNodes" , MD); return; } } while (false); | ||||
| 4737 | Check(IsValidAccessScope(OpMD),do { if (!(IsValidAccessScope(OpMD))) { CheckFailed("Access scope list contains invalid access scope" , MD); return; } } while (false) | ||||
| 4738 | "Access scope list contains invalid access scope", MD)do { if (!(IsValidAccessScope(OpMD))) { CheckFailed("Access scope list contains invalid access scope" , MD); return; } } while (false); | ||||
| 4739 | } | ||||
| 4740 | } | ||||
| 4741 | |||||
| 4742 | /// verifyInstruction - Verify that an instruction is well formed. | ||||
| 4743 | /// | ||||
| 4744 | void Verifier::visitInstruction(Instruction &I) { | ||||
| 4745 | BasicBlock *BB = I.getParent(); | ||||
| 4746 | Check(BB, "Instruction not embedded in basic block!", &I)do { if (!(BB)) { CheckFailed("Instruction not embedded in basic block!" , &I); return; } } while (false); | ||||
| 4747 | |||||
| 4748 | if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential | ||||
| 4749 | for (User *U : I.users()) { | ||||
| 4750 | Check(U != (User *)&I || !DT.isReachableFromEntry(BB),do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false) | ||||
| 4751 | "Only PHI nodes may reference their own value!", &I)do { if (!(U != (User *)&I || !DT.isReachableFromEntry(BB ))) { CheckFailed("Only PHI nodes may reference their own value!" , &I); return; } } while (false); | ||||
| 4752 | } | ||||
| 4753 | } | ||||
| 4754 | |||||
| 4755 | // Check that void typed values don't have names | ||||
| 4756 | Check(!I.getType()->isVoidTy() || !I.hasName(),do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false) | ||||
| 4757 | "Instruction has a name, but provides a void value!", &I)do { if (!(!I.getType()->isVoidTy() || !I.hasName())) { CheckFailed ("Instruction has a name, but provides a void value!", &I ); return; } } while (false); | ||||
| 4758 | |||||
| 4759 | // Check that the return value of the instruction is either void or a legal | ||||
| 4760 | // value type. | ||||
| 4761 | Check(I.getType()->isVoidTy() || I.getType()->isFirstClassType(),do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false) | ||||
| 4762 | "Instruction returns a non-scalar type!", &I)do { if (!(I.getType()->isVoidTy() || I.getType()->isFirstClassType ())) { CheckFailed("Instruction returns a non-scalar type!", & I); return; } } while (false); | ||||
| 4763 | |||||
| 4764 | // Check that the instruction doesn't produce metadata. Calls are already | ||||
| 4765 | // checked against the callee type. | ||||
| 4766 | Check(!I.getType()->isMetadataTy() || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false) | ||||
| 4767 | "Invalid use of metadata!", &I)do { if (!(!I.getType()->isMetadataTy() || isa<CallInst >(I) || isa<InvokeInst>(I))) { CheckFailed("Invalid use of metadata!" , &I); return; } } while (false); | ||||
| 4768 | |||||
| 4769 | // Check that all uses of the instruction, if they are instructions | ||||
| 4770 | // themselves, actually have parent basic blocks. If the use is not an | ||||
| 4771 | // instruction, it is an error! | ||||
| 4772 | for (Use &U : I.uses()) { | ||||
| 4773 | if (Instruction *Used = dyn_cast<Instruction>(U.getUser())) | ||||
| 4774 | Check(Used->getParent() != nullptr,do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4775 | "Instruction referencing"do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4776 | " instruction not embedded in a basic block!",do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false) | ||||
| 4777 | &I, Used)do { if (!(Used->getParent() != nullptr)) { CheckFailed("Instruction referencing" " instruction not embedded in a basic block!", &I, Used) ; return; } } while (false); | ||||
| 4778 | else { | ||||
| 4779 | CheckFailed("Use of instruction is not an instruction!", U); | ||||
| 4780 | return; | ||||
| 4781 | } | ||||
| 4782 | } | ||||
| 4783 | |||||
| 4784 | // Get a pointer to the call base of the instruction if it is some form of | ||||
| 4785 | // call. | ||||
| 4786 | const CallBase *CBI = dyn_cast<CallBase>(&I); | ||||
| 4787 | |||||
| 4788 | for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { | ||||
| 4789 | Check(I.getOperand(i) != nullptr, "Instruction has null operand!", &I)do { if (!(I.getOperand(i) != nullptr)) { CheckFailed("Instruction has null operand!" , &I); return; } } while (false); | ||||
| 4790 | |||||
| 4791 | // Check to make sure that only first-class-values are operands to | ||||
| 4792 | // instructions. | ||||
| 4793 | if (!I.getOperand(i)->getType()->isFirstClassType()) { | ||||
| 4794 | Check(false, "Instruction operands must be first-class values!", &I)do { if (!(false)) { CheckFailed("Instruction operands must be first-class values!" , &I); return; } } while (false); | ||||
| 4795 | } | ||||
| 4796 | |||||
| 4797 | if (Function *F = dyn_cast<Function>(I.getOperand(i))) { | ||||
| 4798 | // This code checks whether the function is used as the operand of a | ||||
| 4799 | // clang_arc_attachedcall operand bundle. | ||||
| 4800 | auto IsAttachedCallOperand = [](Function *F, const CallBase *CBI, | ||||
| 4801 | int Idx) { | ||||
| 4802 | return CBI && CBI->isOperandBundleOfType( | ||||
| 4803 | LLVMContext::OB_clang_arc_attachedcall, Idx); | ||||
| 4804 | }; | ||||
| 4805 | |||||
| 4806 | // Check to make sure that the "address of" an intrinsic function is never | ||||
| 4807 | // taken. Ignore cases where the address of the intrinsic function is used | ||||
| 4808 | // as the argument of operand bundle "clang.arc.attachedcall" as those | ||||
| 4809 | // cases are handled in verifyAttachedCallBundle. | ||||
| 4810 | Check((!F->isIntrinsic() ||do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
| 4811 | (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)) ||do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
| 4812 | IsAttachedCallOperand(F, CBI, i)),do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false) | ||||
| 4813 | "Cannot take the address of an intrinsic!", &I)do { if (!((!F->isIntrinsic() || (CBI && &CBI-> getCalledOperandUse() == &I.getOperandUse(i)) || IsAttachedCallOperand (F, CBI, i)))) { CheckFailed("Cannot take the address of an intrinsic!" , &I); return; } } while (false); | ||||
| 4814 | Check(!F->isIntrinsic() || isa<CallInst>(I) ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4815 | F->getIntrinsicID() == Intrinsic::donothing ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4816 | F->getIntrinsicID() == Intrinsic::seh_try_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4817 | F->getIntrinsicID() == Intrinsic::seh_try_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4818 | F->getIntrinsicID() == Intrinsic::seh_scope_begin ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4819 | F->getIntrinsicID() == Intrinsic::seh_scope_end ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4820 | F->getIntrinsicID() == Intrinsic::coro_resume ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4821 | F->getIntrinsicID() == Intrinsic::coro_destroy ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4822 | F->getIntrinsicID() ==do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4823 | Intrinsic::experimental_patchpoint_void ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4824 | F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4825 | F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4826 | F->getIntrinsicID() == Intrinsic::wasm_rethrow ||do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4827 | IsAttachedCallOperand(F, CBI, i),do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4828 | "Cannot invoke an intrinsic other than donothing, patchpoint, "do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4829 | "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall",do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false) | ||||
| 4830 | &I)do { if (!(!F->isIntrinsic() || isa<CallInst>(I) || F ->getIntrinsicID() == Intrinsic::donothing || F->getIntrinsicID () == Intrinsic::seh_try_begin || F->getIntrinsicID() == Intrinsic ::seh_try_end || F->getIntrinsicID() == Intrinsic::seh_scope_begin || F->getIntrinsicID() == Intrinsic::seh_scope_end || F-> getIntrinsicID() == Intrinsic::coro_resume || F->getIntrinsicID () == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic ::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic ::experimental_gc_statepoint || F->getIntrinsicID() == Intrinsic ::wasm_rethrow || IsAttachedCallOperand(F, CBI, i))) { CheckFailed ("Cannot invoke an intrinsic other than donothing, patchpoint, " "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall" , &I); return; } } while (false); | ||||
| 4831 | Check(F->getParent() == &M, "Referencing function in another module!", &I,do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ) | ||||
| 4832 | &M, F, F->getParent())do { if (!(F->getParent() == &M)) { CheckFailed("Referencing function in another module!" , &I, &M, F, F->getParent()); return; } } while (false ); | ||||
| 4833 | } else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) { | ||||
| 4834 | Check(OpBB->getParent() == BB->getParent(),do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false) | ||||
| 4835 | "Referring to a basic block in another function!", &I)do { if (!(OpBB->getParent() == BB->getParent())) { CheckFailed ("Referring to a basic block in another function!", &I); return ; } } while (false); | ||||
| 4836 | } else if (Argument *OpArg = dyn_cast<Argument>(I.getOperand(i))) { | ||||
| 4837 | Check(OpArg->getParent() == BB->getParent(),do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false) | ||||
| 4838 | "Referring to an argument in another function!", &I)do { if (!(OpArg->getParent() == BB->getParent())) { CheckFailed ("Referring to an argument in another function!", &I); return ; } } while (false); | ||||
| 4839 | } else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) { | ||||
| 4840 | Check(GV->getParent() == &M, "Referencing global in another module!", &I,do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false) | ||||
| 4841 | &M, GV, GV->getParent())do { if (!(GV->getParent() == &M)) { CheckFailed("Referencing global in another module!" , &I, &M, GV, GV->getParent()); return; } } while ( false); | ||||
| 4842 | } else if (isa<Instruction>(I.getOperand(i))) { | ||||
| 4843 | verifyDominatesUse(I, i); | ||||
| 4844 | } else if (isa<InlineAsm>(I.getOperand(i))) { | ||||
| 4845 | Check(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i),do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false) | ||||
| 4846 | "Cannot take the address of an inline asm!", &I)do { if (!(CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i))) { CheckFailed("Cannot take the address of an inline asm!" , &I); return; } } while (false); | ||||
| 4847 | } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I.getOperand(i))) { | ||||
| 4848 | if (CE->getType()->isPtrOrPtrVectorTy()) { | ||||
| 4849 | // If we have a ConstantExpr pointer, we need to see if it came from an | ||||
| 4850 | // illegal bitcast. | ||||
| 4851 | visitConstantExprsRecursively(CE); | ||||
| 4852 | } | ||||
| 4853 | } | ||||
| 4854 | } | ||||
| 4855 | |||||
| 4856 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_fpmath)) { | ||||
| 4857 | Check(I.getType()->isFPOrFPVectorTy(),do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false) | ||||
| 4858 | "fpmath requires a floating point result!", &I)do { if (!(I.getType()->isFPOrFPVectorTy())) { CheckFailed ("fpmath requires a floating point result!", &I); return; } } while (false); | ||||
| 4859 | Check(MD->getNumOperands() == 1, "fpmath takes one operand!", &I)do { if (!(MD->getNumOperands() == 1)) { CheckFailed("fpmath takes one operand!" , &I); return; } } while (false); | ||||
| 4860 | if (ConstantFP *CFP0 = | ||||
| 4861 | mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) { | ||||
| 4862 | const APFloat &Accuracy = CFP0->getValueAPF(); | ||||
| 4863 | Check(&Accuracy.getSemantics() == &APFloat::IEEEsingle(),do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false) | ||||
| 4864 | "fpmath accuracy must have float type", &I)do { if (!(&Accuracy.getSemantics() == &APFloat::IEEEsingle ())) { CheckFailed("fpmath accuracy must have float type", & I); return; } } while (false); | ||||
| 4865 | Check(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false) | ||||
| 4866 | "fpmath accuracy not a positive number!", &I)do { if (!(Accuracy.isFiniteNonZero() && !Accuracy.isNegative ())) { CheckFailed("fpmath accuracy not a positive number!", & I); return; } } while (false); | ||||
| 4867 | } else { | ||||
| 4868 | Check(false, "invalid fpmath accuracy!", &I)do { if (!(false)) { CheckFailed("invalid fpmath accuracy!", & I); return; } } while (false); | ||||
| 4869 | } | ||||
| 4870 | } | ||||
| 4871 | |||||
| 4872 | if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { | ||||
| 4873 | Check(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I),do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false) | ||||
| 4874 | "Ranges are only for loads, calls and invokes!", &I)do { if (!(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I))) { CheckFailed("Ranges are only for loads, calls and invokes!" , &I); return; } } while (false); | ||||
| 4875 | visitRangeMetadata(I, Range, I.getType()); | ||||
| 4876 | } | ||||
| 4877 | |||||
| 4878 | if (I.hasMetadata(LLVMContext::MD_invariant_group)) { | ||||
| 4879 | Check(isa<LoadInst>(I) || isa<StoreInst>(I),do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I)) ) { CheckFailed("invariant.group metadata is only for loads and stores" , &I); return; } } while (false) | ||||
| 4880 | "invariant.group metadata is only for loads and stores", &I)do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I)) ) { CheckFailed("invariant.group metadata is only for loads and stores" , &I); return; } } while (false); | ||||
| 4881 | } | ||||
| 4882 | |||||
| 4883 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_nonnull)) { | ||||
| 4884 | Check(I.getType()->isPointerTy(), "nonnull applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false) | ||||
| 4885 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("nonnull applies only to pointer types" , &I); return; } } while (false); | ||||
| 4886 | Check(isa<LoadInst>(I),do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4887 | "nonnull applies only to load instructions, use attributes"do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4888 | " for calls or invokes",do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false) | ||||
| 4889 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("nonnull applies only to load instructions, use attributes" " for calls or invokes", &I); return; } } while (false); | ||||
| 4890 | Check(MD->getNumOperands() == 0, "nonnull metadata must be empty", &I)do { if (!(MD->getNumOperands() == 0)) { CheckFailed("nonnull metadata must be empty" , &I); return; } } while (false); | ||||
| 4891 | } | ||||
| 4892 | |||||
| 4893 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable)) | ||||
| 4894 | visitDereferenceableMetadata(I, MD); | ||||
| 4895 | |||||
| 4896 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) | ||||
| 4897 | visitDereferenceableMetadata(I, MD); | ||||
| 4898 | |||||
| 4899 | if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) | ||||
| 4900 | TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); | ||||
| 4901 | |||||
| 4902 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) | ||||
| 4903 | visitAliasScopeListMetadata(MD); | ||||
| 4904 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) | ||||
| 4905 | visitAliasScopeListMetadata(MD); | ||||
| 4906 | |||||
| 4907 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_access_group)) | ||||
| 4908 | visitAccessGroupMetadata(MD); | ||||
| 4909 | |||||
| 4910 | if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { | ||||
| 4911 | Check(I.getType()->isPointerTy(), "align applies only to pointer types",do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false) | ||||
| 4912 | &I)do { if (!(I.getType()->isPointerTy())) { CheckFailed("align applies only to pointer types" , &I); return; } } while (false); | ||||
| 4913 | Check(isa<LoadInst>(I),do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
| 4914 | "align applies only to load instructions, "do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
| 4915 | "use attributes for calls or invokes",do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false) | ||||
| 4916 | &I)do { if (!(isa<LoadInst>(I))) { CheckFailed("align applies only to load instructions, " "use attributes for calls or invokes", &I); return; } } while (false); | ||||
| 4917 | Check(AlignMD->getNumOperands() == 1, "align takes one operand!", &I)do { if (!(AlignMD->getNumOperands() == 1)) { CheckFailed( "align takes one operand!", &I); return; } } while (false ); | ||||
| 4918 | ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0)); | ||||
| 4919 | Check(CI && CI->getType()->isIntegerTy(64),do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false) | ||||
| 4920 | "align metadata value must be an i64!", &I)do { if (!(CI && CI->getType()->isIntegerTy(64) )) { CheckFailed("align metadata value must be an i64!", & I); return; } } while (false); | ||||
| 4921 | uint64_t Align = CI->getZExtValue(); | ||||
| 4922 | Check(isPowerOf2_64(Align), "align metadata value must be a power of 2!",do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false) | ||||
| 4923 | &I)do { if (!(isPowerOf2_64(Align))) { CheckFailed("align metadata value must be a power of 2!" , &I); return; } } while (false); | ||||
| 4924 | Check(Align <= Value::MaximumAlignment,do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false) | ||||
| 4925 | "alignment is larger that implementation defined limit", &I)do { if (!(Align <= Value::MaximumAlignment)) { CheckFailed ("alignment is larger that implementation defined limit", & I); return; } } while (false); | ||||
| 4926 | } | ||||
| 4927 | |||||
| 4928 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_prof)) | ||||
| 4929 | visitProfMetadata(I, MD); | ||||
| 4930 | |||||
| 4931 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_memprof)) | ||||
| 4932 | visitMemProfMetadata(I, MD); | ||||
| 4933 | |||||
| 4934 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_callsite)) | ||||
| 4935 | visitCallsiteMetadata(I, MD); | ||||
| 4936 | |||||
| 4937 | if (MDNode *MD = I.getMetadata(LLVMContext::MD_DIAssignID)) | ||||
| 4938 | visitDIAssignIDMetadata(I, MD); | ||||
| 4939 | |||||
| 4940 | if (MDNode *Annotation = I.getMetadata(LLVMContext::MD_annotation)) | ||||
| 4941 | visitAnnotationMetadata(Annotation); | ||||
| 4942 | |||||
| 4943 | if (MDNode *N = I.getDebugLoc().getAsMDNode()) { | ||||
| 4944 | CheckDI(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N)do { if (!(isa<DILocation>(N))) { DebugInfoCheckFailed( "invalid !dbg metadata attachment", &I, N); return; } } while (false); | ||||
| 4945 | visitMDNode(*N, AreDebugLocsAllowed::Yes); | ||||
| 4946 | } | ||||
| 4947 | |||||
| 4948 | if (auto *DII = dyn_cast<DbgVariableIntrinsic>(&I)) { | ||||
| 4949 | verifyFragmentExpression(*DII); | ||||
| 4950 | verifyNotEntryValue(*DII); | ||||
| 4951 | } | ||||
| 4952 | |||||
| 4953 | SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; | ||||
| 4954 | I.getAllMetadata(MDs); | ||||
| 4955 | for (auto Attachment : MDs) { | ||||
| 4956 | unsigned Kind = Attachment.first; | ||||
| 4957 | auto AllowLocs = | ||||
| 4958 | (Kind == LLVMContext::MD_dbg || Kind == LLVMContext::MD_loop) | ||||
| 4959 | ? AreDebugLocsAllowed::Yes | ||||
| 4960 | : AreDebugLocsAllowed::No; | ||||
| 4961 | visitMDNode(*Attachment.second, AllowLocs); | ||||
| 4962 | } | ||||
| 4963 | |||||
| 4964 | InstsInThisBlock.insert(&I); | ||||
| 4965 | } | ||||
| 4966 | |||||
| 4967 | /// Allow intrinsics to be verified in different ways. | ||||
| 4968 | void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | ||||
| 4969 | Function *IF = Call.getCalledFunction(); | ||||
| 4970 | Check(IF->isDeclaration(), "Intrinsic functions should never be defined!",do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false) | ||||
| 4971 | IF)do { if (!(IF->isDeclaration())) { CheckFailed("Intrinsic functions should never be defined!" , IF); return; } } while (false); | ||||
| 4972 | |||||
| 4973 | // Verify that the intrinsic prototype lines up with what the .td files | ||||
| 4974 | // describe. | ||||
| 4975 | FunctionType *IFTy = IF->getFunctionType(); | ||||
| 4976 | bool IsVarArg = IFTy->isVarArg(); | ||||
| 4977 | |||||
| 4978 | SmallVector<Intrinsic::IITDescriptor, 8> Table; | ||||
| 4979 | getIntrinsicInfoTableEntries(ID, Table); | ||||
| 4980 | ArrayRef<Intrinsic::IITDescriptor> TableRef = Table; | ||||
| 4981 | |||||
| 4982 | // Walk the descriptors to extract overloaded types. | ||||
| 4983 | SmallVector<Type *, 4> ArgTys; | ||||
| 4984 | Intrinsic::MatchIntrinsicTypesResult Res = | ||||
| 4985 | Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys); | ||||
| 4986 | Check(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false) | ||||
| 4987 | "Intrinsic has incorrect return type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet)) { CheckFailed("Intrinsic has incorrect return type!", IF); return ; } } while (false); | ||||
| 4988 | Check(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false) | ||||
| 4989 | "Intrinsic has incorrect argument type!", IF)do { if (!(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg)) { CheckFailed("Intrinsic has incorrect argument type!", IF); return; } } while (false); | ||||
| 4990 | |||||
| 4991 | // Verify if the intrinsic call matches the vararg property. | ||||
| 4992 | if (IsVarArg) | ||||
| 4993 | Check(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false) | ||||
| 4994 | "Intrinsic was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Intrinsic was not defined with variable arguments!" , IF); return; } } while (false); | ||||
| 4995 | else | ||||
| 4996 | Check(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef),do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false) | ||||
| 4997 | "Callsite was not defined with variable arguments!", IF)do { if (!(!Intrinsic::matchIntrinsicVarArg(IsVarArg, TableRef ))) { CheckFailed("Callsite was not defined with variable arguments!" , IF); return; } } while (false); | ||||
| 4998 | |||||
| 4999 | // All descriptors should be absorbed by now. | ||||
| 5000 | Check(TableRef.empty(), "Intrinsic has too few arguments!", IF)do { if (!(TableRef.empty())) { CheckFailed("Intrinsic has too few arguments!" , IF); return; } } while (false); | ||||
| 5001 | |||||
| 5002 | // Now that we have the intrinsic ID and the actual argument types (and we | ||||
| 5003 | // know they are legal for the intrinsic!) get the intrinsic name through the | ||||
| 5004 | // usual means. This allows us to verify the mangling of argument types into | ||||
| 5005 | // the name. | ||||
| 5006 | const std::string ExpectedName = | ||||
| 5007 | Intrinsic::getName(ID, ArgTys, IF->getParent(), IFTy); | ||||
| 5008 | Check(ExpectedName == IF->getName(),do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 5009 | "Intrinsic name not mangled correctly for type arguments! "do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 5010 | "Should be: " +do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 5011 | ExpectedName,do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false) | ||||
| 5012 | IF)do { if (!(ExpectedName == IF->getName())) { CheckFailed("Intrinsic name not mangled correctly for type arguments! " "Should be: " + ExpectedName, IF); return; } } while (false); | ||||
| 5013 | |||||
| 5014 | // If the intrinsic takes MDNode arguments, verify that they are either global | ||||
| 5015 | // or are local to *this* function. | ||||
| 5016 | for (Value *V : Call.args()) { | ||||
| 5017 | if (auto *MD = dyn_cast<MetadataAsValue>(V)) | ||||
| 5018 | visitMetadataAsValue(*MD, Call.getCaller()); | ||||
| 5019 | if (auto *Const = dyn_cast<Constant>(V)) | ||||
| 5020 | Check(!Const->getType()->isX86_AMXTy(),do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false) | ||||
| 5021 | "const x86_amx is not allowed in argument!")do { if (!(!Const->getType()->isX86_AMXTy())) { CheckFailed ("const x86_amx is not allowed in argument!"); return; } } while (false); | ||||
| 5022 | } | ||||
| 5023 | |||||
| 5024 | switch (ID) { | ||||
| 5025 | default: | ||||
| 5026 | break; | ||||
| 5027 | case Intrinsic::assume: { | ||||
| 5028 | for (auto &Elem : Call.bundle_op_infos()) { | ||||
| 5029 | unsigned ArgCount = Elem.End - Elem.Begin; | ||||
| 5030 | // Separate storage assumptions are special insofar as they're the only | ||||
| 5031 | // operand bundles allowed on assumes that aren't parameter attributes. | ||||
| 5032 | if (Elem.Tag->getKey() == "separate_storage") { | ||||
| 5033 | Check(ArgCount == 2,do { if (!(ArgCount == 2)) { CheckFailed("separate_storage assumptions should have 2 arguments" , Call); return; } } while (false) | ||||
| 5034 | "separate_storage assumptions should have 2 arguments", Call)do { if (!(ArgCount == 2)) { CheckFailed("separate_storage assumptions should have 2 arguments" , Call); return; } } while (false); | ||||
| 5035 | Check(Call.getOperand(Elem.Begin)->getType()->isPointerTy() &&do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
| 5036 | Call.getOperand(Elem.Begin + 1)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
| 5037 | "arguments to separate_storage assumptions should be pointers",do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false) | ||||
| 5038 | Call)do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy () && Call.getOperand(Elem.Begin + 1)->getType()-> isPointerTy())) { CheckFailed("arguments to separate_storage assumptions should be pointers" , Call); return; } } while (false); | ||||
| 5039 | return; | ||||
| 5040 | } | ||||
| 5041 | Check(Elem.Tag->getKey() == "ignore" ||do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false) | ||||
| 5042 | Attribute::isExistingAttribute(Elem.Tag->getKey()),do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false) | ||||
| 5043 | "tags must be valid attribute names", Call)do { if (!(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute (Elem.Tag->getKey()))) { CheckFailed("tags must be valid attribute names" , Call); return; } } while (false); | ||||
| 5044 | Attribute::AttrKind Kind = | ||||
| 5045 | Attribute::getAttrKindFromName(Elem.Tag->getKey()); | ||||
| 5046 | if (Kind == Attribute::Alignment) { | ||||
| 5047 | Check(ArgCount <= 3 && ArgCount >= 2,do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments", Call); return; } } while (false) | ||||
| 5048 | "alignment assumptions should have 2 or 3 arguments", Call)do { if (!(ArgCount <= 3 && ArgCount >= 2)) { CheckFailed ("alignment assumptions should have 2 or 3 arguments", Call); return; } } while (false); | ||||
| 5049 | Check(Call.getOperand(Elem.Begin)->getType()->isPointerTy(),do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer", Call ); return; } } while (false) | ||||
| 5050 | "first argument should be a pointer", Call)do { if (!(Call.getOperand(Elem.Begin)->getType()->isPointerTy ())) { CheckFailed("first argument should be a pointer", Call ); return; } } while (false); | ||||
| 5051 | Check(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" , Call); return; } } while (false) | ||||
| 5052 | "second argument should be an integer", Call)do { if (!(Call.getOperand(Elem.Begin + 1)->getType()-> isIntegerTy())) { CheckFailed("second argument should be an integer" , Call); return; } } while (false); | ||||
| 5053 | if (ArgCount == 3) | ||||
| 5054 | Check(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(),do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" , Call); return; } } while (false) | ||||
| 5055 | "third argument should be an integer if present", Call)do { if (!(Call.getOperand(Elem.Begin + 2)->getType()-> isIntegerTy())) { CheckFailed("third argument should be an integer if present" , Call); return; } } while (false); | ||||
| 5056 | return; | ||||
| 5057 | } | ||||
| 5058 | Check(ArgCount <= 2, "too many arguments", Call)do { if (!(ArgCount <= 2)) { CheckFailed("too many arguments" , Call); return; } } while (false); | ||||
| 5059 | if (Kind == Attribute::None) | ||||
| 5060 | break; | ||||
| 5061 | if (Attribute::isIntAttrKind(Kind)) { | ||||
| 5062 | Check(ArgCount == 2, "this attribute should have 2 arguments", Call)do { if (!(ArgCount == 2)) { CheckFailed("this attribute should have 2 arguments" , Call); return; } } while (false); | ||||
| 5063 | Check(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)),do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" , Call); return; } } while (false) | ||||
| 5064 | "the second argument should be a constant integral value", Call)do { if (!(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)))) { CheckFailed("the second argument should be a constant integral value" , Call); return; } } while (false); | ||||
| 5065 | } else if (Attribute::canUseAsParamAttr(Kind)) { | ||||
| 5066 | Check((ArgCount) == 1, "this attribute should have one argument", Call)do { if (!((ArgCount) == 1)) { CheckFailed("this attribute should have one argument" , Call); return; } } while (false); | ||||
| 5067 | } else if (Attribute::canUseAsFnAttr(Kind)) { | ||||
| 5068 | Check((ArgCount) == 0, "this attribute has no argument", Call)do { if (!((ArgCount) == 0)) { CheckFailed("this attribute has no argument" , Call); return; } } while (false); | ||||
| 5069 | } | ||||
| 5070 | } | ||||
| 5071 | break; | ||||
| 5072 | } | ||||
| 5073 | case Intrinsic::coro_id: { | ||||
| 5074 | auto *InfoArg = Call.getArgOperand(3)->stripPointerCasts(); | ||||
| 5075 | if (isa<ConstantPointerNull>(InfoArg)) | ||||
| 5076 | break; | ||||
| 5077 | auto *GV = dyn_cast<GlobalVariable>(InfoArg); | ||||
| 5078 | Check(GV && GV->isConstant() && GV->hasDefinitiveInitializer(),do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
| 5079 | "info argument of llvm.coro.id must refer to an initialized "do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false) | ||||
| 5080 | "constant")do { if (!(GV && GV->isConstant() && GV-> hasDefinitiveInitializer())) { CheckFailed("info argument of llvm.coro.id must refer to an initialized " "constant"); return; } } while (false); | ||||
| 5081 | Constant *Init = GV->getInitializer(); | ||||
| 5082 | Check(isa<ConstantStruct>(Init) || isa<ConstantArray>(Init),do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
| 5083 | "info argument of llvm.coro.id must refer to either a struct or "do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false) | ||||
| 5084 | "an array")do { if (!(isa<ConstantStruct>(Init) || isa<ConstantArray >(Init))) { CheckFailed("info argument of llvm.coro.id must refer to either a struct or " "an array"); return; } } while (false); | ||||
| 5085 | break; | ||||
| 5086 | } | ||||
| 5087 | case Intrinsic::is_fpclass: { | ||||
| 5088 | const ConstantInt *TestMask = cast<ConstantInt>(Call.getOperand(1)); | ||||
| 5089 | Check((TestMask->getZExtValue() & ~static_cast<unsigned>(fcAllFlags)) == 0,do { if (!((TestMask->getZExtValue() & ~static_cast< unsigned>(fcAllFlags)) == 0)) { CheckFailed("unsupported bits for llvm.is.fpclass test mask" ); return; } } while (false) | ||||
| 5090 | "unsupported bits for llvm.is.fpclass test mask")do { if (!((TestMask->getZExtValue() & ~static_cast< unsigned>(fcAllFlags)) == 0)) { CheckFailed("unsupported bits for llvm.is.fpclass test mask" ); return; } } while (false); | ||||
| 5091 | break; | ||||
| 5092 | } | ||||
| 5093 | case Intrinsic::fptrunc_round: { | ||||
| 5094 | // Check the rounding mode | ||||
| 5095 | Metadata *MD = nullptr; | ||||
| 5096 | auto *MAV = dyn_cast<MetadataAsValue>(Call.getOperand(1)); | ||||
| 5097 | if (MAV) | ||||
| 5098 | MD = MAV->getMetadata(); | ||||
| 5099 | |||||
| 5100 | Check(MD != nullptr, "missing rounding mode argument", Call)do { if (!(MD != nullptr)) { CheckFailed("missing rounding mode argument" , Call); return; } } while (false); | ||||
| 5101 | |||||
| 5102 | Check(isa<MDString>(MD),do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
| 5103 | ("invalid value for llvm.fptrunc.round metadata operand"do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
| 5104 | " (the operand should be a string)"),do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false) | ||||
| 5105 | MD)do { if (!(isa<MDString>(MD))) { CheckFailed(("invalid value for llvm.fptrunc.round metadata operand" " (the operand should be a string)"), MD); return; } } while (false); | ||||
| 5106 | |||||
| 5107 | std::optional<RoundingMode> RoundMode = | ||||
| 5108 | convertStrToRoundingMode(cast<MDString>(MD)->getString()); | ||||
| 5109 | Check(RoundMode && *RoundMode != RoundingMode::Dynamic,do { if (!(RoundMode && *RoundMode != RoundingMode::Dynamic )) { CheckFailed("unsupported rounding mode argument", Call); return; } } while (false) | ||||
| 5110 | "unsupported rounding mode argument", Call)do { if (!(RoundMode && *RoundMode != RoundingMode::Dynamic )) { CheckFailed("unsupported rounding mode argument", Call); return; } } while (false); | ||||
| 5111 | break; | ||||
| 5112 | } | ||||
| 5113 | #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: | ||||
| 5114 | #include "llvm/IR/VPIntrinsics.def" | ||||
| 5115 | visitVPIntrinsic(cast<VPIntrinsic>(Call)); | ||||
| 5116 | break; | ||||
| 5117 | #define INSTRUCTION(NAME, NARGS, ROUND_MODE, INTRINSIC) \ | ||||
| 5118 | case Intrinsic::INTRINSIC: | ||||
| 5119 | #include "llvm/IR/ConstrainedOps.def" | ||||
| 5120 | visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(Call)); | ||||
| 5121 | break; | ||||
| 5122 | case Intrinsic::dbg_declare: // llvm.dbg.declare | ||||
| 5123 | Check(isa<MetadataAsValue>(Call.getArgOperand(0)),do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false) | ||||
| 5124 | "invalid llvm.dbg.declare intrinsic call 1", Call)do { if (!(isa<MetadataAsValue>(Call.getArgOperand(0))) ) { CheckFailed("invalid llvm.dbg.declare intrinsic call 1", Call ); return; } } while (false); | ||||
| 5125 | visitDbgIntrinsic("declare", cast<DbgVariableIntrinsic>(Call)); | ||||
| 5126 | break; | ||||
| 5127 | case Intrinsic::dbg_value: // llvm.dbg.value | ||||
| 5128 | visitDbgIntrinsic("value", cast<DbgVariableIntrinsic>(Call)); | ||||
| 5129 | break; | ||||
| 5130 | case Intrinsic::dbg_assign: // llvm.dbg.assign | ||||
| 5131 | visitDbgIntrinsic("assign", cast<DbgVariableIntrinsic>(Call)); | ||||
| 5132 | break; | ||||
| 5133 | case Intrinsic::dbg_label: // llvm.dbg.label | ||||
| 5134 | visitDbgLabelIntrinsic("label", cast<DbgLabelInst>(Call)); | ||||
| 5135 | break; | ||||
| 5136 | case Intrinsic::memcpy: | ||||
| 5137 | case Intrinsic::memcpy_inline: | ||||
| 5138 | case Intrinsic::memmove: | ||||
| 5139 | case Intrinsic::memset: | ||||
| 5140 | case Intrinsic::memset_inline: { | ||||
| 5141 | break; | ||||
| 5142 | } | ||||
| 5143 | case Intrinsic::memcpy_element_unordered_atomic: | ||||
| 5144 | case Intrinsic::memmove_element_unordered_atomic: | ||||
| 5145 | case Intrinsic::memset_element_unordered_atomic: { | ||||
| 5146 | const auto *AMI = cast<AtomicMemIntrinsic>(&Call); | ||||
| 5147 | |||||
| 5148 | ConstantInt *ElementSizeCI = | ||||
| 5149 | cast<ConstantInt>(AMI->getRawElementSizeInBytes()); | ||||
| 5150 | const APInt &ElementSizeVal = ElementSizeCI->getValue(); | ||||
| 5151 | Check(ElementSizeVal.isPowerOf2(),do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 5152 | "element size of the element-wise atomic memory intrinsic "do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 5153 | "must be a power of 2",do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false) | ||||
| 5154 | Call)do { if (!(ElementSizeVal.isPowerOf2())) { CheckFailed("element size of the element-wise atomic memory intrinsic " "must be a power of 2", Call); return; } } while (false); | ||||
| 5155 | |||||
| 5156 | auto IsValidAlignment = [&](MaybeAlign Alignment) { | ||||
| 5157 | return Alignment && ElementSizeVal.ule(Alignment->value()); | ||||
| 5158 | }; | ||||
| 5159 | Check(IsValidAlignment(AMI->getDestAlign()),do { if (!(IsValidAlignment(AMI->getDestAlign()))) { CheckFailed ("incorrect alignment of the destination argument", Call); return ; } } while (false) | ||||
| 5160 | "incorrect alignment of the destination argument", Call)do { if (!(IsValidAlignment(AMI->getDestAlign()))) { CheckFailed ("incorrect alignment of the destination argument", Call); return ; } } while (false); | ||||
| 5161 | if (const auto *AMT = dyn_cast<AtomicMemTransferInst>(AMI)) { | ||||
| 5162 | Check(IsValidAlignment(AMT->getSourceAlign()),do { if (!(IsValidAlignment(AMT->getSourceAlign()))) { CheckFailed ("incorrect alignment of the source argument", Call); return; } } while (false) | ||||
| 5163 | "incorrect alignment of the source argument", Call)do { if (!(IsValidAlignment(AMT->getSourceAlign()))) { CheckFailed ("incorrect alignment of the source argument", Call); return; } } while (false); | ||||
| 5164 | } | ||||
| 5165 | break; | ||||
| 5166 | } | ||||
| 5167 | case Intrinsic::call_preallocated_setup: { | ||||
| 5168 | auto *NumArgs = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
| 5169 | Check(NumArgs != nullptr,do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false) | ||||
| 5170 | "llvm.call.preallocated.setup argument must be a constant")do { if (!(NumArgs != nullptr)) { CheckFailed("llvm.call.preallocated.setup argument must be a constant" ); return; } } while (false); | ||||
| 5171 | bool FoundCall = false; | ||||
| 5172 | for (User *U : Call.users()) { | ||||
| 5173 | auto *UseCall = dyn_cast<CallBase>(U); | ||||
| 5174 | Check(UseCall != nullptr,do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false) | ||||
| 5175 | "Uses of llvm.call.preallocated.setup must be calls")do { if (!(UseCall != nullptr)) { CheckFailed("Uses of llvm.call.preallocated.setup must be calls" ); return; } } while (false); | ||||
| 5176 | const Function *Fn = UseCall->getCalledFunction(); | ||||
| 5177 | if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { | ||||
| 5178 | auto *AllocArgIndex = dyn_cast<ConstantInt>(UseCall->getArgOperand(1)); | ||||
| 5179 | Check(AllocArgIndex != nullptr,do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false) | ||||
| 5180 | "llvm.call.preallocated.alloc arg index must be a constant")do { if (!(AllocArgIndex != nullptr)) { CheckFailed("llvm.call.preallocated.alloc arg index must be a constant" ); return; } } while (false); | ||||
| 5181 | auto AllocArgIndexInt = AllocArgIndex->getValue(); | ||||
| 5182 | Check(AllocArgIndexInt.sge(0) &&do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 5183 | AllocArgIndexInt.slt(NumArgs->getValue()),do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 5184 | "llvm.call.preallocated.alloc arg index must be between 0 and "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 5185 | "corresponding "do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false) | ||||
| 5186 | "llvm.call.preallocated.setup's argument count")do { if (!(AllocArgIndexInt.sge(0) && AllocArgIndexInt .slt(NumArgs->getValue()))) { CheckFailed("llvm.call.preallocated.alloc arg index must be between 0 and " "corresponding " "llvm.call.preallocated.setup's argument count" ); return; } } while (false); | ||||
| 5187 | } else if (Fn && Fn->getIntrinsicID() == | ||||
| 5188 | Intrinsic::call_preallocated_teardown) { | ||||
| 5189 | // nothing to do | ||||
| 5190 | } else { | ||||
| 5191 | Check(!FoundCall, "Can have at most one call corresponding to a "do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 5192 | "llvm.call.preallocated.setup")do { if (!(!FoundCall)) { CheckFailed("Can have at most one call corresponding to a " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
| 5193 | FoundCall = true; | ||||
| 5194 | size_t NumPreallocatedArgs = 0; | ||||
| 5195 | for (unsigned i = 0; i < UseCall->arg_size(); i++) { | ||||
| 5196 | if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { | ||||
| 5197 | ++NumPreallocatedArgs; | ||||
| 5198 | } | ||||
| 5199 | } | ||||
| 5200 | Check(NumPreallocatedArgs != 0,do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
| 5201 | "cannot use preallocated intrinsics on a call without "do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false) | ||||
| 5202 | "preallocated arguments")do { if (!(NumPreallocatedArgs != 0)) { CheckFailed("cannot use preallocated intrinsics on a call without " "preallocated arguments"); return; } } while (false); | ||||
| 5203 | Check(NumArgs->equalsInt(NumPreallocatedArgs),do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 5204 | "llvm.call.preallocated.setup arg size must be equal to number "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 5205 | "of preallocated arguments "do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 5206 | "at call site",do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false) | ||||
| 5207 | Call, *UseCall)do { if (!(NumArgs->equalsInt(NumPreallocatedArgs))) { CheckFailed ("llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " "at call site", Call, *UseCall) ; return; } } while (false); | ||||
| 5208 | // getOperandBundle() cannot be called if more than one of the operand | ||||
| 5209 | // bundle exists. There is already a check elsewhere for this, so skip | ||||
| 5210 | // here if we see more than one. | ||||
| 5211 | if (UseCall->countOperandBundlesOfType(LLVMContext::OB_preallocated) > | ||||
| 5212 | 1) { | ||||
| 5213 | return; | ||||
| 5214 | } | ||||
| 5215 | auto PreallocatedBundle = | ||||
| 5216 | UseCall->getOperandBundle(LLVMContext::OB_preallocated); | ||||
| 5217 | Check(PreallocatedBundle,do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
| 5218 | "Use of llvm.call.preallocated.setup outside intrinsics "do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false) | ||||
| 5219 | "must be in \"preallocated\" operand bundle")do { if (!(PreallocatedBundle)) { CheckFailed("Use of llvm.call.preallocated.setup outside intrinsics " "must be in \"preallocated\" operand bundle"); return; } } while (false); | ||||
| 5220 | Check(PreallocatedBundle->Inputs.front().get() == &Call,do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 5221 | "preallocated bundle must have token from corresponding "do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false) | ||||
| 5222 | "llvm.call.preallocated.setup")do { if (!(PreallocatedBundle->Inputs.front().get() == & Call)) { CheckFailed("preallocated bundle must have token from corresponding " "llvm.call.preallocated.setup"); return; } } while (false); | ||||
| 5223 | } | ||||
| 5224 | } | ||||
| 5225 | break; | ||||
| 5226 | } | ||||
| 5227 | case Intrinsic::call_preallocated_arg: { | ||||
| 5228 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
| 5229 | Check(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5230 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5231 | "llvm.call.preallocated.arg token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5232 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.arg token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
| 5233 | Check(Call.hasFnAttr(Attribute::Preallocated),do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
| 5234 | "llvm.call.preallocated.arg must be called with a \"preallocated\" "do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false) | ||||
| 5235 | "call site attribute")do { if (!(Call.hasFnAttr(Attribute::Preallocated))) { CheckFailed ("llvm.call.preallocated.arg must be called with a \"preallocated\" " "call site attribute"); return; } } while (false); | ||||
| 5236 | break; | ||||
| 5237 | } | ||||
| 5238 | case Intrinsic::call_preallocated_teardown: { | ||||
| 5239 | auto *Token = dyn_cast<CallBase>(Call.getArgOperand(0)); | ||||
| 5240 | Check(Token && Token->getCalledFunction()->getIntrinsicID() ==do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5241 | Intrinsic::call_preallocated_setup,do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5242 | "llvm.call.preallocated.teardown token argument must be a "do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false) | ||||
| 5243 | "llvm.call.preallocated.setup")do { if (!(Token && Token->getCalledFunction()-> getIntrinsicID() == Intrinsic::call_preallocated_setup)) { CheckFailed ("llvm.call.preallocated.teardown token argument must be a " "llvm.call.preallocated.setup" ); return; } } while (false); | ||||
| 5244 | break; | ||||
| 5245 | } | ||||
| 5246 | case Intrinsic::gcroot: | ||||
| 5247 | case Intrinsic::gcwrite: | ||||
| 5248 | case Intrinsic::gcread: | ||||
| 5249 | if (ID == Intrinsic::gcroot) { | ||||
| 5250 | AllocaInst *AI = | ||||
| 5251 | dyn_cast<AllocaInst>(Call.getArgOperand(0)->stripPointerCasts()); | ||||
| 5252 | Check(AI, "llvm.gcroot parameter #1 must be an alloca.", Call)do { if (!(AI)) { CheckFailed("llvm.gcroot parameter #1 must be an alloca." , Call); return; } } while (false); | ||||
| 5253 | Check(isa<Constant>(Call.getArgOperand(1)),do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false) | ||||
| 5254 | "llvm.gcroot parameter #2 must be a constant.", Call)do { if (!(isa<Constant>(Call.getArgOperand(1)))) { CheckFailed ("llvm.gcroot parameter #2 must be a constant.", Call); return ; } } while (false); | ||||
| 5255 | if (!AI->getAllocatedType()->isPointerTy()) { | ||||
| 5256 | Check(!isa<ConstantPointerNull>(Call.getArgOperand(1)),do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 5257 | "llvm.gcroot parameter #1 must either be a pointer alloca, "do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 5258 | "or argument #2 must be a non-null constant.",do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false) | ||||
| 5259 | Call)do { if (!(!isa<ConstantPointerNull>(Call.getArgOperand (1)))) { CheckFailed("llvm.gcroot parameter #1 must either be a pointer alloca, " "or argument #2 must be a non-null constant.", Call); return ; } } while (false); | ||||
| 5260 | } | ||||
| 5261 | } | ||||
| 5262 | |||||
| 5263 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 5264 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 5265 | break; | ||||
| 5266 | case Intrinsic::init_trampoline: | ||||
| 5267 | Check(isa<Function>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
| 5268 | "llvm.init_trampoline parameter #2 must resolve to a function.",do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false) | ||||
| 5269 | Call)do { if (!(isa<Function>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.init_trampoline parameter #2 must resolve to a function." , Call); return; } } while (false); | ||||
| 5270 | break; | ||||
| 5271 | case Intrinsic::prefetch: | ||||
| 5272 | Check(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("rw argument to llvm.prefetch must be 0-1" , Call); return; } } while (false) | ||||
| 5273 | "rw argument to llvm.prefetch must be 0-1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("rw argument to llvm.prefetch must be 0-1" , Call); return; } } while (false); | ||||
| 5274 | Check(cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("locality argument to llvm.prefetch must be 0-4" , Call); return; } } while (false) | ||||
| 5275 | "locality argument to llvm.prefetch must be 0-4", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("locality argument to llvm.prefetch must be 0-4" , Call); return; } } while (false); | ||||
| 5276 | Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("cache type argument to llvm.prefetch must be 0-1" , Call); return; } } while (false) | ||||
| 5277 | "cache type argument to llvm.prefetch must be 0-1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("cache type argument to llvm.prefetch must be 0-1" , Call); return; } } while (false); | ||||
| 5278 | break; | ||||
| 5279 | case Intrinsic::stackprotector: | ||||
| 5280 | Check(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts()),do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false) | ||||
| 5281 | "llvm.stackprotector parameter #2 must resolve to an alloca.", Call)do { if (!(isa<AllocaInst>(Call.getArgOperand(1)->stripPointerCasts ()))) { CheckFailed("llvm.stackprotector parameter #2 must resolve to an alloca." , Call); return; } } while (false); | ||||
| 5282 | break; | ||||
| 5283 | case Intrinsic::localescape: { | ||||
| 5284 | BasicBlock *BB = Call.getParent(); | ||||
| 5285 | Check(BB->isEntryBlock(), "llvm.localescape used outside of entry block",do { if (!(BB->isEntryBlock())) { CheckFailed("llvm.localescape used outside of entry block" , Call); return; } } while (false) | ||||
| 5286 | Call)do { if (!(BB->isEntryBlock())) { CheckFailed("llvm.localescape used outside of entry block" , Call); return; } } while (false); | ||||
| 5287 | Check(!SawFrameEscape, "multiple calls to llvm.localescape in one function",do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false) | ||||
| 5288 | Call)do { if (!(!SawFrameEscape)) { CheckFailed("multiple calls to llvm.localescape in one function" , Call); return; } } while (false); | ||||
| 5289 | for (Value *Arg : Call.args()) { | ||||
| 5290 | if (isa<ConstantPointerNull>(Arg)) | ||||
| 5291 | continue; // Null values are allowed as placeholders. | ||||
| 5292 | auto *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts()); | ||||
| 5293 | Check(AI && AI->isStaticAlloca(),do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false) | ||||
| 5294 | "llvm.localescape only accepts static allocas", Call)do { if (!(AI && AI->isStaticAlloca())) { CheckFailed ("llvm.localescape only accepts static allocas", Call); return ; } } while (false); | ||||
| 5295 | } | ||||
| 5296 | FrameEscapeInfo[BB->getParent()].first = Call.arg_size(); | ||||
| 5297 | SawFrameEscape = true; | ||||
| 5298 | break; | ||||
| 5299 | } | ||||
| 5300 | case Intrinsic::localrecover: { | ||||
| 5301 | Value *FnArg = Call.getArgOperand(0)->stripPointerCasts(); | ||||
| 5302 | Function *Fn = dyn_cast<Function>(FnArg); | ||||
| 5303 | Check(Fn && !Fn->isDeclaration(),do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 5304 | "llvm.localrecover first "do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 5305 | "argument must be function defined in this module",do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false) | ||||
| 5306 | Call)do { if (!(Fn && !Fn->isDeclaration())) { CheckFailed ("llvm.localrecover first " "argument must be function defined in this module" , Call); return; } } while (false); | ||||
| 5307 | auto *IdxArg = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5308 | auto &Entry = FrameEscapeInfo[Fn]; | ||||
| 5309 | Entry.second = unsigned( | ||||
| 5310 | std::max(uint64_t(Entry.second), IdxArg->getLimitedValue(~0U) + 1)); | ||||
| 5311 | break; | ||||
| 5312 | } | ||||
| 5313 | |||||
| 5314 | case Intrinsic::experimental_gc_statepoint: | ||||
| 5315 | if (auto *CI = dyn_cast<CallInst>(&Call)) | ||||
| 5316 | Check(!CI->isInlineAsm(),do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false) | ||||
| 5317 | "gc.statepoint support for inline assembly unimplemented", CI)do { if (!(!CI->isInlineAsm())) { CheckFailed("gc.statepoint support for inline assembly unimplemented" , CI); return; } } while (false); | ||||
| 5318 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 5319 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 5320 | |||||
| 5321 | verifyStatepoint(Call); | ||||
| 5322 | break; | ||||
| 5323 | case Intrinsic::experimental_gc_result: { | ||||
| 5324 | Check(Call.getParent()->getParent()->hasGC(),do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false) | ||||
| 5325 | "Enclosing function does not use GC.", Call)do { if (!(Call.getParent()->getParent()->hasGC())) { CheckFailed ("Enclosing function does not use GC.", Call); return; } } while (false); | ||||
| 5326 | |||||
| 5327 | auto *Statepoint = Call.getArgOperand(0); | ||||
| 5328 | if (isa<UndefValue>(Statepoint)) | ||||
| 5329 | break; | ||||
| 5330 | |||||
| 5331 | // Are we tied to a statepoint properly? | ||||
| 5332 | const auto *StatepointCall = dyn_cast<CallBase>(Statepoint); | ||||
| 5333 | const Function *StatepointFn = | ||||
| 5334 | StatepointCall ? StatepointCall->getCalledFunction() : nullptr; | ||||
| 5335 | Check(StatepointFn && StatepointFn->isDeclaration() &&do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 5336 | StatepointFn->getIntrinsicID() ==do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 5337 | Intrinsic::experimental_gc_statepoint,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 5338 | "gc.result operand #1 must be from a statepoint", Call,do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false) | ||||
| 5339 | Call.getArgOperand(0))do { if (!(StatepointFn && StatepointFn->isDeclaration () && StatepointFn->getIntrinsicID() == Intrinsic:: experimental_gc_statepoint)) { CheckFailed("gc.result operand #1 must be from a statepoint" , Call, Call.getArgOperand(0)); return; } } while (false); | ||||
| 5340 | |||||
| 5341 | // Check that result type matches wrapped callee. | ||||
| 5342 | auto *TargetFuncType = | ||||
| 5343 | cast<FunctionType>(StatepointCall->getParamElementType(2)); | ||||
| 5344 | Check(Call.getType() == TargetFuncType->getReturnType(),do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false) | ||||
| 5345 | "gc.result result type does not match wrapped callee", Call)do { if (!(Call.getType() == TargetFuncType->getReturnType ())) { CheckFailed("gc.result result type does not match wrapped callee" , Call); return; } } while (false); | ||||
| 5346 | break; | ||||
| 5347 | } | ||||
| 5348 | case Intrinsic::experimental_gc_relocate: { | ||||
| 5349 | Check(Call.arg_size() == 3, "wrong number of arguments", Call)do { if (!(Call.arg_size() == 3)) { CheckFailed("wrong number of arguments" , Call); return; } } while (false); | ||||
| 5350 | |||||
| 5351 | Check(isa<PointerType>(Call.getType()->getScalarType()),do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false) | ||||
| 5352 | "gc.relocate must return a pointer or a vector of pointers", Call)do { if (!(isa<PointerType>(Call.getType()->getScalarType ()))) { CheckFailed("gc.relocate must return a pointer or a vector of pointers" , Call); return; } } while (false); | ||||
| 5353 | |||||
| 5354 | // Check that this relocate is correctly tied to the statepoint | ||||
| 5355 | |||||
| 5356 | // This is case for relocate on the unwinding path of an invoke statepoint | ||||
| 5357 | if (LandingPadInst *LandingPad = | ||||
| 5358 | dyn_cast<LandingPadInst>(Call.getArgOperand(0))) { | ||||
| 5359 | |||||
| 5360 | const BasicBlock *InvokeBB = | ||||
| 5361 | LandingPad->getParent()->getUniquePredecessor(); | ||||
| 5362 | |||||
| 5363 | // Landingpad relocates should have only one predecessor with invoke | ||||
| 5364 | // statepoint terminator | ||||
| 5365 | Check(InvokeBB, "safepoints should have unique landingpads",do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false) | ||||
| 5366 | LandingPad->getParent())do { if (!(InvokeBB)) { CheckFailed("safepoints should have unique landingpads" , LandingPad->getParent()); return; } } while (false); | ||||
| 5367 | Check(InvokeBB->getTerminator(), "safepoint block should be well formed",do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false) | ||||
| 5368 | InvokeBB)do { if (!(InvokeBB->getTerminator())) { CheckFailed("safepoint block should be well formed" , InvokeBB); return; } } while (false); | ||||
| 5369 | Check(isa<GCStatepointInst>(InvokeBB->getTerminator()),do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false) | ||||
| 5370 | "gc relocate should be linked to a statepoint", InvokeBB)do { if (!(isa<GCStatepointInst>(InvokeBB->getTerminator ()))) { CheckFailed("gc relocate should be linked to a statepoint" , InvokeBB); return; } } while (false); | ||||
| 5371 | } else { | ||||
| 5372 | // In all other cases relocate should be tied to the statepoint directly. | ||||
| 5373 | // This covers relocates on a normal return path of invoke statepoint and | ||||
| 5374 | // relocates of a call statepoint. | ||||
| 5375 | auto *Token = Call.getArgOperand(0); | ||||
| 5376 | Check(isa<GCStatepointInst>(Token) || isa<UndefValue>(Token),do { if (!(isa<GCStatepointInst>(Token) || isa<UndefValue >(Token))) { CheckFailed("gc relocate is incorrectly tied to the statepoint" , Call, Token); return; } } while (false) | ||||
| 5377 | "gc relocate is incorrectly tied to the statepoint", Call, Token)do { if (!(isa<GCStatepointInst>(Token) || isa<UndefValue >(Token))) { CheckFailed("gc relocate is incorrectly tied to the statepoint" , Call, Token); return; } } while (false); | ||||
| 5378 | } | ||||
| 5379 | |||||
| 5380 | // Verify rest of the relocate arguments. | ||||
| 5381 | const Value &StatepointCall = *cast<GCRelocateInst>(Call).getStatepoint(); | ||||
| 5382 | |||||
| 5383 | // Both the base and derived must be piped through the safepoint. | ||||
| 5384 | Value *Base = Call.getArgOperand(1); | ||||
| 5385 | Check(isa<ConstantInt>(Base),do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false) | ||||
| 5386 | "gc.relocate operand #2 must be integer offset", Call)do { if (!(isa<ConstantInt>(Base))) { CheckFailed("gc.relocate operand #2 must be integer offset" , Call); return; } } while (false); | ||||
| 5387 | |||||
| 5388 | Value *Derived = Call.getArgOperand(2); | ||||
| 5389 | Check(isa<ConstantInt>(Derived),do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false) | ||||
| 5390 | "gc.relocate operand #3 must be integer offset", Call)do { if (!(isa<ConstantInt>(Derived))) { CheckFailed("gc.relocate operand #3 must be integer offset" , Call); return; } } while (false); | ||||
| 5391 | |||||
| 5392 | const uint64_t BaseIndex = cast<ConstantInt>(Base)->getZExtValue(); | ||||
| 5393 | const uint64_t DerivedIndex = cast<ConstantInt>(Derived)->getZExtValue(); | ||||
| 5394 | |||||
| 5395 | // Check the bounds | ||||
| 5396 | if (isa<UndefValue>(StatepointCall)) | ||||
| 5397 | break; | ||||
| 5398 | if (auto Opt = cast<GCStatepointInst>(StatepointCall) | ||||
| 5399 | .getOperandBundle(LLVMContext::OB_gc_live)) { | ||||
| 5400 | Check(BaseIndex < Opt->Inputs.size(),do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false) | ||||
| 5401 | "gc.relocate: statepoint base index out of bounds", Call)do { if (!(BaseIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint base index out of bounds", Call); return ; } } while (false); | ||||
| 5402 | Check(DerivedIndex < Opt->Inputs.size(),do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false) | ||||
| 5403 | "gc.relocate: statepoint derived index out of bounds", Call)do { if (!(DerivedIndex < Opt->Inputs.size())) { CheckFailed ("gc.relocate: statepoint derived index out of bounds", Call) ; return; } } while (false); | ||||
| 5404 | } | ||||
| 5405 | |||||
| 5406 | // Relocated value must be either a pointer type or vector-of-pointer type, | ||||
| 5407 | // but gc_relocate does not need to return the same pointer type as the | ||||
| 5408 | // relocated pointer. It can be casted to the correct type later if it's | ||||
| 5409 | // desired. However, they must have the same address space and 'vectorness' | ||||
| 5410 | GCRelocateInst &Relocate = cast<GCRelocateInst>(Call); | ||||
| 5411 | auto *ResultType = Call.getType(); | ||||
| 5412 | auto *DerivedType = Relocate.getDerivedPtr()->getType(); | ||||
| 5413 | auto *BaseType = Relocate.getBasePtr()->getType(); | ||||
| 5414 | |||||
| 5415 | Check(BaseType->isPtrOrPtrVectorTy(),do { if (!(BaseType->isPtrOrPtrVectorTy())) { CheckFailed( "gc.relocate: relocated value must be a pointer", Call); return ; } } while (false) | ||||
| 5416 | "gc.relocate: relocated value must be a pointer", Call)do { if (!(BaseType->isPtrOrPtrVectorTy())) { CheckFailed( "gc.relocate: relocated value must be a pointer", Call); return ; } } while (false); | ||||
| 5417 | Check(DerivedType->isPtrOrPtrVectorTy(),do { if (!(DerivedType->isPtrOrPtrVectorTy())) { CheckFailed ("gc.relocate: relocated value must be a pointer", Call); return ; } } while (false) | ||||
| 5418 | "gc.relocate: relocated value must be a pointer", Call)do { if (!(DerivedType->isPtrOrPtrVectorTy())) { CheckFailed ("gc.relocate: relocated value must be a pointer", Call); return ; } } while (false); | ||||
| 5419 | |||||
| 5420 | Check(ResultType->isVectorTy() == DerivedType->isVectorTy(),do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
| 5421 | "gc.relocate: vector relocates to vector and pointer to pointer",do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false) | ||||
| 5422 | Call)do { if (!(ResultType->isVectorTy() == DerivedType->isVectorTy ())) { CheckFailed("gc.relocate: vector relocates to vector and pointer to pointer" , Call); return; } } while (false); | ||||
| 5423 | Check(do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 5424 | ResultType->getPointerAddressSpace() ==do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 5425 | DerivedType->getPointerAddressSpace(),do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 5426 | "gc.relocate: relocating a pointer shouldn't change its address space",do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false) | ||||
| 5427 | Call)do { if (!(ResultType->getPointerAddressSpace() == DerivedType ->getPointerAddressSpace())) { CheckFailed("gc.relocate: relocating a pointer shouldn't change its address space" , Call); return; } } while (false); | ||||
| 5428 | |||||
| 5429 | auto GC = llvm::getGCStrategy(Relocate.getFunction()->getGC()); | ||||
| 5430 | Check(GC, "gc.relocate: calling function must have GCStrategy",do { if (!(GC)) { CheckFailed("gc.relocate: calling function must have GCStrategy" , Call.getFunction()); return; } } while (false) | ||||
| 5431 | Call.getFunction())do { if (!(GC)) { CheckFailed("gc.relocate: calling function must have GCStrategy" , Call.getFunction()); return; } } while (false); | ||||
| 5432 | if (GC) { | ||||
| 5433 | auto isGCPtr = [&GC](Type *PTy) { | ||||
| 5434 | return GC->isGCManagedPointer(PTy->getScalarType()).value_or(true); | ||||
| 5435 | }; | ||||
| 5436 | Check(isGCPtr(ResultType), "gc.relocate: must return gc pointer", Call)do { if (!(isGCPtr(ResultType))) { CheckFailed("gc.relocate: must return gc pointer" , Call); return; } } while (false); | ||||
| 5437 | Check(isGCPtr(BaseType),do { if (!(isGCPtr(BaseType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
| 5438 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(isGCPtr(BaseType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
| 5439 | Check(isGCPtr(DerivedType),do { if (!(isGCPtr(DerivedType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false) | ||||
| 5440 | "gc.relocate: relocated value must be a gc pointer", Call)do { if (!(isGCPtr(DerivedType))) { CheckFailed("gc.relocate: relocated value must be a gc pointer" , Call); return; } } while (false); | ||||
| 5441 | } | ||||
| 5442 | break; | ||||
| 5443 | } | ||||
| 5444 | case Intrinsic::eh_exceptioncode: | ||||
| 5445 | case Intrinsic::eh_exceptionpointer: { | ||||
| 5446 | Check(isa<CatchPadInst>(Call.getArgOperand(0)),do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false) | ||||
| 5447 | "eh.exceptionpointer argument must be a catchpad", Call)do { if (!(isa<CatchPadInst>(Call.getArgOperand(0)))) { CheckFailed("eh.exceptionpointer argument must be a catchpad" , Call); return; } } while (false); | ||||
| 5448 | break; | ||||
| 5449 | } | ||||
| 5450 | case Intrinsic::get_active_lane_mask: { | ||||
| 5451 | Check(Call.getType()->isVectorTy(),do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
| 5452 | "get_active_lane_mask: must return a "do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
| 5453 | "vector",do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false) | ||||
| 5454 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("get_active_lane_mask: must return a " "vector", Call); return; } } while (false); | ||||
| 5455 | auto *ElemTy = Call.getType()->getScalarType(); | ||||
| 5456 | Check(ElemTy->isIntegerTy(1),do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
| 5457 | "get_active_lane_mask: element type is not "do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
| 5458 | "i1",do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false) | ||||
| 5459 | Call)do { if (!(ElemTy->isIntegerTy(1))) { CheckFailed("get_active_lane_mask: element type is not " "i1", Call); return; } } while (false); | ||||
| 5460 | break; | ||||
| 5461 | } | ||||
| 5462 | case Intrinsic::masked_load: { | ||||
| 5463 | Check(Call.getType()->isVectorTy(), "masked_load: must return a vector",do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false) | ||||
| 5464 | Call)do { if (!(Call.getType()->isVectorTy())) { CheckFailed("masked_load: must return a vector" , Call); return; } } while (false); | ||||
| 5465 | |||||
| 5466 | Value *Ptr = Call.getArgOperand(0); | ||||
| 5467 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 5468 | Value *Mask = Call.getArgOperand(2); | ||||
| 5469 | Value *PassThru = Call.getArgOperand(3); | ||||
| 5470 | Check(Mask->getType()->isVectorTy(), "masked_load: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false) | ||||
| 5471 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_load: mask must be vector", Call); return; } } while (false); | ||||
| 5472 | Check(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false) | ||||
| 5473 | "masked_load: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_load: alignment must be a power of 2", Call); return ; } } while (false); | ||||
| 5474 | |||||
| 5475 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
| 5476 | Check(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false) | ||||
| 5477 | "masked_load: return must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Call.getType ()))) { CheckFailed("masked_load: return must match pointer type" , Call); return; } } while (false); | ||||
| 5478 | Check(PassThru->getType() == Call.getType(),do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false) | ||||
| 5479 | "masked_load: pass through and return type must match", Call)do { if (!(PassThru->getType() == Call.getType())) { CheckFailed ("masked_load: pass through and return type must match", Call ); return; } } while (false); | ||||
| 5480 | Check(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
| 5481 | cast<VectorType>(Call.getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false) | ||||
| 5482 | "masked_load: vector mask must be same length as return", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Call.getType())->getElementCount ())) { CheckFailed("masked_load: vector mask must be same length as return" , Call); return; } } while (false); | ||||
| 5483 | break; | ||||
| 5484 | } | ||||
| 5485 | case Intrinsic::masked_store: { | ||||
| 5486 | Value *Val = Call.getArgOperand(0); | ||||
| 5487 | Value *Ptr = Call.getArgOperand(1); | ||||
| 5488 | ConstantInt *Alignment = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5489 | Value *Mask = Call.getArgOperand(3); | ||||
| 5490 | Check(Mask->getType()->isVectorTy(), "masked_store: mask must be vector",do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false) | ||||
| 5491 | Call)do { if (!(Mask->getType()->isVectorTy())) { CheckFailed ("masked_store: mask must be vector", Call); return; } } while (false); | ||||
| 5492 | Check(Alignment->getValue().isPowerOf2(),do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false) | ||||
| 5493 | "masked_store: alignment must be a power of 2", Call)do { if (!(Alignment->getValue().isPowerOf2())) { CheckFailed ("masked_store: alignment must be a power of 2", Call); return ; } } while (false); | ||||
| 5494 | |||||
| 5495 | PointerType *PtrTy = cast<PointerType>(Ptr->getType()); | ||||
| 5496 | Check(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType()),do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false) | ||||
| 5497 | "masked_store: storee must match pointer type", Call)do { if (!(PtrTy->isOpaqueOrPointeeTypeMatches(Val->getType ()))) { CheckFailed("masked_store: storee must match pointer type" , Call); return; } } while (false); | ||||
| 5498 | Check(cast<VectorType>(Mask->getType())->getElementCount() ==do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
| 5499 | cast<VectorType>(Val->getType())->getElementCount(),do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false) | ||||
| 5500 | "masked_store: vector mask must be same length as value", Call)do { if (!(cast<VectorType>(Mask->getType())->getElementCount () == cast<VectorType>(Val->getType())->getElementCount ())) { CheckFailed("masked_store: vector mask must be same length as value" , Call); return; } } while (false); | ||||
| 5501 | break; | ||||
| 5502 | } | ||||
| 5503 | |||||
| 5504 | case Intrinsic::masked_gather: { | ||||
| 5505 | const APInt &Alignment = | ||||
| 5506 | cast<ConstantInt>(Call.getArgOperand(1))->getValue(); | ||||
| 5507 | Check(Alignment.isZero() || Alignment.isPowerOf2(),do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_gather: alignment must be 0 or a power of 2", Call); return; } } while (false) | ||||
| 5508 | "masked_gather: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_gather: alignment must be 0 or a power of 2", Call); return; } } while (false); | ||||
| 5509 | break; | ||||
| 5510 | } | ||||
| 5511 | case Intrinsic::masked_scatter: { | ||||
| 5512 | const APInt &Alignment = | ||||
| 5513 | cast<ConstantInt>(Call.getArgOperand(2))->getValue(); | ||||
| 5514 | Check(Alignment.isZero() || Alignment.isPowerOf2(),do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_scatter: alignment must be 0 or a power of 2", Call) ; return; } } while (false) | ||||
| 5515 | "masked_scatter: alignment must be 0 or a power of 2", Call)do { if (!(Alignment.isZero() || Alignment.isPowerOf2())) { CheckFailed ("masked_scatter: alignment must be 0 or a power of 2", Call) ; return; } } while (false); | ||||
| 5516 | break; | ||||
| 5517 | } | ||||
| 5518 | |||||
| 5519 | case Intrinsic::experimental_guard: { | ||||
| 5520 | Check(isa<CallInst>(Call), "experimental_guard cannot be invoked", Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_guard cannot be invoked" , Call); return; } } while (false); | ||||
| 5521 | Check(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5522 | "experimental_guard must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5523 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_guard must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
| 5524 | break; | ||||
| 5525 | } | ||||
| 5526 | |||||
| 5527 | case Intrinsic::experimental_deoptimize: { | ||||
| 5528 | Check(isa<CallInst>(Call), "experimental_deoptimize cannot be invoked",do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false) | ||||
| 5529 | Call)do { if (!(isa<CallInst>(Call))) { CheckFailed("experimental_deoptimize cannot be invoked" , Call); return; } } while (false); | ||||
| 5530 | Check(Call.countOperandBundlesOfType(LLVMContext::OB_deopt) == 1,do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5531 | "experimental_deoptimize must have exactly one "do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false) | ||||
| 5532 | "\"deopt\" operand bundle")do { if (!(Call.countOperandBundlesOfType(LLVMContext::OB_deopt ) == 1)) { CheckFailed("experimental_deoptimize must have exactly one " "\"deopt\" operand bundle"); return; } } while (false); | ||||
| 5533 | Check(Call.getType() == Call.getFunction()->getReturnType(),do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false) | ||||
| 5534 | "experimental_deoptimize return type must match caller return type")do { if (!(Call.getType() == Call.getFunction()->getReturnType ())) { CheckFailed("experimental_deoptimize return type must match caller return type" ); return; } } while (false); | ||||
| 5535 | |||||
| 5536 | if (isa<CallInst>(Call)) { | ||||
| 5537 | auto *RI = dyn_cast<ReturnInst>(Call.getNextNode()); | ||||
| 5538 | Check(RI,do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false) | ||||
| 5539 | "calls to experimental_deoptimize must be followed by a return")do { if (!(RI)) { CheckFailed("calls to experimental_deoptimize must be followed by a return" ); return; } } while (false); | ||||
| 5540 | |||||
| 5541 | if (!Call.getType()->isVoidTy() && RI) | ||||
| 5542 | Check(RI->getReturnValue() == &Call,do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
| 5543 | "calls to experimental_deoptimize must be followed by a return "do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false) | ||||
| 5544 | "of the value computed by experimental_deoptimize")do { if (!(RI->getReturnValue() == &Call)) { CheckFailed ("calls to experimental_deoptimize must be followed by a return " "of the value computed by experimental_deoptimize"); return; } } while (false); | ||||
| 5545 | } | ||||
| 5546 | |||||
| 5547 | break; | ||||
| 5548 | } | ||||
| 5549 | case Intrinsic::vector_reduce_and: | ||||
| 5550 | case Intrinsic::vector_reduce_or: | ||||
| 5551 | case Intrinsic::vector_reduce_xor: | ||||
| 5552 | case Intrinsic::vector_reduce_add: | ||||
| 5553 | case Intrinsic::vector_reduce_mul: | ||||
| 5554 | case Intrinsic::vector_reduce_smax: | ||||
| 5555 | case Intrinsic::vector_reduce_smin: | ||||
| 5556 | case Intrinsic::vector_reduce_umax: | ||||
| 5557 | case Intrinsic::vector_reduce_umin: { | ||||
| 5558 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
| 5559 | Check(ArgTy->isIntOrIntVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5560 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isIntOrIntVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5561 | break; | ||||
| 5562 | } | ||||
| 5563 | case Intrinsic::vector_reduce_fmax: | ||||
| 5564 | case Intrinsic::vector_reduce_fmin: { | ||||
| 5565 | Type *ArgTy = Call.getArgOperand(0)->getType(); | ||||
| 5566 | Check(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5567 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5568 | break; | ||||
| 5569 | } | ||||
| 5570 | case Intrinsic::vector_reduce_fadd: | ||||
| 5571 | case Intrinsic::vector_reduce_fmul: { | ||||
| 5572 | // Unlike the other reductions, the first argument is a start value. The | ||||
| 5573 | // second argument is the vector to be reduced. | ||||
| 5574 | Type *ArgTy = Call.getArgOperand(1)->getType(); | ||||
| 5575 | Check(ArgTy->isFPOrFPVectorTy() && ArgTy->isVectorTy(),do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false) | ||||
| 5576 | "Intrinsic has incorrect argument type!")do { if (!(ArgTy->isFPOrFPVectorTy() && ArgTy-> isVectorTy())) { CheckFailed("Intrinsic has incorrect argument type!" ); return; } } while (false); | ||||
| 5577 | break; | ||||
| 5578 | } | ||||
| 5579 | case Intrinsic::smul_fix: | ||||
| 5580 | case Intrinsic::smul_fix_sat: | ||||
| 5581 | case Intrinsic::umul_fix: | ||||
| 5582 | case Intrinsic::umul_fix_sat: | ||||
| 5583 | case Intrinsic::sdiv_fix: | ||||
| 5584 | case Intrinsic::sdiv_fix_sat: | ||||
| 5585 | case Intrinsic::udiv_fix: | ||||
| 5586 | case Intrinsic::udiv_fix_sat: { | ||||
| 5587 | Value *Op1 = Call.getArgOperand(0); | ||||
| 5588 | Value *Op2 = Call.getArgOperand(1); | ||||
| 5589 | Check(Op1->getType()->isIntOrIntVectorTy(),do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5590 | "first operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5591 | "vector of ints")do { if (!(Op1->getType()->isIntOrIntVectorTy())) { CheckFailed ("first operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
| 5592 | Check(Op2->getType()->isIntOrIntVectorTy(),do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5593 | "second operand of [us][mul|div]_fix[_sat] must be an int type or "do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false) | ||||
| 5594 | "vector of ints")do { if (!(Op2->getType()->isIntOrIntVectorTy())) { CheckFailed ("second operand of [us][mul|div]_fix[_sat] must be an int type or " "vector of ints"); return; } } while (false); | ||||
| 5595 | |||||
| 5596 | auto *Op3 = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5597 | Check(Op3->getType()->getBitWidth() <= 32,do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false) | ||||
| 5598 | "third argument of [us][mul|div]_fix[_sat] must fit within 32 bits")do { if (!(Op3->getType()->getBitWidth() <= 32)) { CheckFailed ("third argument of [us][mul|div]_fix[_sat] must fit within 32 bits" ); return; } } while (false); | ||||
| 5599 | |||||
| 5600 | if (ID == Intrinsic::smul_fix || ID == Intrinsic::smul_fix_sat || | ||||
| 5601 | ID == Intrinsic::sdiv_fix || ID == Intrinsic::sdiv_fix_sat) { | ||||
| 5602 | Check(Op3->getZExtValue() < Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
| 5603 | "the scale of s[mul|div]_fix[_sat] must be less than the width of "do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false) | ||||
| 5604 | "the operands")do { if (!(Op3->getZExtValue() < Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of s[mul|div]_fix[_sat] must be less than the width of " "the operands"); return; } } while (false); | ||||
| 5605 | } else { | ||||
| 5606 | Check(Op3->getZExtValue() <= Op1->getType()->getScalarSizeInBits(),do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
| 5607 | "the scale of u[mul|div]_fix[_sat] must be less than or equal "do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false) | ||||
| 5608 | "to the width of the operands")do { if (!(Op3->getZExtValue() <= Op1->getType()-> getScalarSizeInBits())) { CheckFailed("the scale of u[mul|div]_fix[_sat] must be less than or equal " "to the width of the operands"); return; } } while (false); | ||||
| 5609 | } | ||||
| 5610 | break; | ||||
| 5611 | } | ||||
| 5612 | case Intrinsic::lround: | ||||
| 5613 | case Intrinsic::llround: | ||||
| 5614 | case Intrinsic::lrint: | ||||
| 5615 | case Intrinsic::llrint: { | ||||
| 5616 | Type *ValTy = Call.getArgOperand(0)->getType(); | ||||
| 5617 | Type *ResultTy = Call.getType(); | ||||
| 5618 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false) | ||||
| 5619 | "Intrinsic does not support vectors", &Call)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & Call); return; } } while (false); | ||||
| 5620 | break; | ||||
| 5621 | } | ||||
| 5622 | case Intrinsic::bswap: { | ||||
| 5623 | Type *Ty = Call.getType(); | ||||
| 5624 | unsigned Size = Ty->getScalarSizeInBits(); | ||||
| 5625 | Check(Size % 16 == 0, "bswap must be an even number of bytes", &Call)do { if (!(Size % 16 == 0)) { CheckFailed("bswap must be an even number of bytes" , &Call); return; } } while (false); | ||||
| 5626 | break; | ||||
| 5627 | } | ||||
| 5628 | case Intrinsic::invariant_start: { | ||||
| 5629 | ConstantInt *InvariantSize = dyn_cast<ConstantInt>(Call.getArgOperand(0)); | ||||
| 5630 | Check(InvariantSize &&do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5631 | (!InvariantSize->isNegative() || InvariantSize->isMinusOne()),do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5632 | "invariant_start parameter must be -1, 0 or a positive number",do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false) | ||||
| 5633 | &Call)do { if (!(InvariantSize && (!InvariantSize->isNegative () || InvariantSize->isMinusOne()))) { CheckFailed("invariant_start parameter must be -1, 0 or a positive number" , &Call); return; } } while (false); | ||||
| 5634 | break; | ||||
| 5635 | } | ||||
| 5636 | case Intrinsic::matrix_multiply: | ||||
| 5637 | case Intrinsic::matrix_transpose: | ||||
| 5638 | case Intrinsic::matrix_column_major_load: | ||||
| 5639 | case Intrinsic::matrix_column_major_store: { | ||||
| 5640 | Function *IF = Call.getCalledFunction(); | ||||
| 5641 | ConstantInt *Stride = nullptr; | ||||
| 5642 | ConstantInt *NumRows; | ||||
| 5643 | ConstantInt *NumColumns; | ||||
| 5644 | VectorType *ResultTy; | ||||
| 5645 | Type *Op0ElemTy = nullptr; | ||||
| 5646 | Type *Op1ElemTy = nullptr; | ||||
| 5647 | switch (ID) { | ||||
| 5648 | case Intrinsic::matrix_multiply: { | ||||
| 5649 | NumRows = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5650 | ConstantInt *N = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
| 5651 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5652 | Check(cast<FixedVectorType>(Call.getArgOperand(0)->getType())do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5653 | ->getNumElements() ==do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5654 | NumRows->getZExtValue() * N->getZExtValue(),do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5655 | "First argument of a matrix operation does not match specified "do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5656 | "shape!")do { if (!(cast<FixedVectorType>(Call.getArgOperand(0)-> getType()) ->getNumElements() == NumRows->getZExtValue( ) * N->getZExtValue())) { CheckFailed("First argument of a matrix operation does not match specified " "shape!"); return; } } while (false); | ||||
| 5657 | Check(cast<FixedVectorType>(Call.getArgOperand(1)->getType())do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5658 | ->getNumElements() ==do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5659 | N->getZExtValue() * NumColumns->getZExtValue(),do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5660 | "Second argument of a matrix operation does not match specified "do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false) | ||||
| 5661 | "shape!")do { if (!(cast<FixedVectorType>(Call.getArgOperand(1)-> getType()) ->getNumElements() == N->getZExtValue() * NumColumns ->getZExtValue())) { CheckFailed("Second argument of a matrix operation does not match specified " "shape!"); return; } } while (false); | ||||
| 5662 | |||||
| 5663 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5664 | Op0ElemTy = | ||||
| 5665 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5666 | Op1ElemTy = | ||||
| 5667 | cast<VectorType>(Call.getArgOperand(1)->getType())->getElementType(); | ||||
| 5668 | break; | ||||
| 5669 | } | ||||
| 5670 | case Intrinsic::matrix_transpose: | ||||
| 5671 | NumRows = cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 5672 | NumColumns = cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5673 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5674 | Op0ElemTy = | ||||
| 5675 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5676 | break; | ||||
| 5677 | case Intrinsic::matrix_column_major_load: { | ||||
| 5678 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(1)); | ||||
| 5679 | NumRows = cast<ConstantInt>(Call.getArgOperand(3)); | ||||
| 5680 | NumColumns = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5681 | ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5682 | |||||
| 5683 | PointerType *Op0PtrTy = | ||||
| 5684 | cast<PointerType>(Call.getArgOperand(0)->getType()); | ||||
| 5685 | if (!Op0PtrTy->isOpaque()) | ||||
| 5686 | Op0ElemTy = Op0PtrTy->getNonOpaquePointerElementType(); | ||||
| 5687 | break; | ||||
| 5688 | } | ||||
| 5689 | case Intrinsic::matrix_column_major_store: { | ||||
| 5690 | Stride = dyn_cast<ConstantInt>(Call.getArgOperand(2)); | ||||
| 5691 | NumRows = cast<ConstantInt>(Call.getArgOperand(4)); | ||||
| 5692 | NumColumns = cast<ConstantInt>(Call.getArgOperand(5)); | ||||
| 5693 | ResultTy = cast<VectorType>(Call.getArgOperand(0)->getType()); | ||||
| 5694 | Op0ElemTy = | ||||
| 5695 | cast<VectorType>(Call.getArgOperand(0)->getType())->getElementType(); | ||||
| 5696 | |||||
| 5697 | PointerType *Op1PtrTy = | ||||
| 5698 | cast<PointerType>(Call.getArgOperand(1)->getType()); | ||||
| 5699 | if (!Op1PtrTy->isOpaque()) | ||||
| 5700 | Op1ElemTy = Op1PtrTy->getNonOpaquePointerElementType(); | ||||
| 5701 | break; | ||||
| 5702 | } | ||||
| 5703 | default: | ||||
| 5704 | llvm_unreachable("unexpected intrinsic")::llvm::llvm_unreachable_internal("unexpected intrinsic", "llvm/lib/IR/Verifier.cpp" , 5704); | ||||
| 5705 | } | ||||
| 5706 | |||||
| 5707 | Check(ResultTy->getElementType()->isIntegerTy() ||do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
| 5708 | ResultTy->getElementType()->isFloatingPointTy(),do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false) | ||||
| 5709 | "Result type must be an integer or floating-point type!", IF)do { if (!(ResultTy->getElementType()->isIntegerTy() || ResultTy->getElementType()->isFloatingPointTy())) { CheckFailed ("Result type must be an integer or floating-point type!", IF ); return; } } while (false); | ||||
| 5710 | |||||
| 5711 | if (Op0ElemTy) | ||||
| 5712 | Check(ResultTy->getElementType() == Op0ElemTy,do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
| 5713 | "Vector element type mismatch of the result and first operand "do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
| 5714 | "vector!",do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false) | ||||
| 5715 | IF)do { if (!(ResultTy->getElementType() == Op0ElemTy)) { CheckFailed ("Vector element type mismatch of the result and first operand " "vector!", IF); return; } } while (false); | ||||
| 5716 | |||||
| 5717 | if (Op1ElemTy) | ||||
| 5718 | Check(ResultTy->getElementType() == Op1ElemTy,do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
| 5719 | "Vector element type mismatch of the result and second operand "do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
| 5720 | "vector!",do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false) | ||||
| 5721 | IF)do { if (!(ResultTy->getElementType() == Op1ElemTy)) { CheckFailed ("Vector element type mismatch of the result and second operand " "vector!", IF); return; } } while (false); | ||||
| 5722 | |||||
| 5723 | Check(cast<FixedVectorType>(ResultTy)->getNumElements() ==do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
| 5724 | NumRows->getZExtValue() * NumColumns->getZExtValue(),do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false) | ||||
| 5725 | "Result of a matrix operation does not fit in the returned vector!")do { if (!(cast<FixedVectorType>(ResultTy)->getNumElements () == NumRows->getZExtValue() * NumColumns->getZExtValue ())) { CheckFailed("Result of a matrix operation does not fit in the returned vector!" ); return; } } while (false); | ||||
| 5726 | |||||
| 5727 | if (Stride) | ||||
| 5728 | Check(Stride->getZExtValue() >= NumRows->getZExtValue(),do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false) | ||||
| 5729 | "Stride must be greater or equal than the number of rows!", IF)do { if (!(Stride->getZExtValue() >= NumRows->getZExtValue ())) { CheckFailed("Stride must be greater or equal than the number of rows!" , IF); return; } } while (false); | ||||
| 5730 | |||||
| 5731 | break; | ||||
| 5732 | } | ||||
| 5733 | case Intrinsic::experimental_vector_splice: { | ||||
| 5734 | VectorType *VecTy = cast<VectorType>(Call.getType()); | ||||
| 5735 | int64_t Idx = cast<ConstantInt>(Call.getArgOperand(2))->getSExtValue(); | ||||
| 5736 | int64_t KnownMinNumElements = VecTy->getElementCount().getKnownMinValue(); | ||||
| 5737 | if (Call.getParent() && Call.getParent()->getParent()) { | ||||
| 5738 | AttributeList Attrs = Call.getParent()->getParent()->getAttributes(); | ||||
| 5739 | if (Attrs.hasFnAttr(Attribute::VScaleRange)) | ||||
| 5740 | KnownMinNumElements *= Attrs.getFnAttrs().getVScaleRangeMin(); | ||||
| 5741 | } | ||||
| 5742 | Check((Idx < 0 && std::abs(Idx) <= KnownMinNumElements) ||do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5743 | (Idx >= 0 && Idx < KnownMinNumElements),do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5744 | "The splice index exceeds the range [-VL, VL-1] where VL is the "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5745 | "known minimum number of elements in the vector. For scalable "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5746 | "vectors the minimum number of elements is determined from "do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5747 | "vscale_range.",do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false) | ||||
| 5748 | &Call)do { if (!((Idx < 0 && std::abs(Idx) <= KnownMinNumElements ) || (Idx >= 0 && Idx < KnownMinNumElements))) { CheckFailed("The splice index exceeds the range [-VL, VL-1] where VL is the " "known minimum number of elements in the vector. For scalable " "vectors the minimum number of elements is determined from " "vscale_range.", &Call); return; } } while (false); | ||||
| 5749 | break; | ||||
| 5750 | } | ||||
| 5751 | case Intrinsic::experimental_stepvector: { | ||||
| 5752 | VectorType *VecTy = dyn_cast<VectorType>(Call.getType()); | ||||
| 5753 | Check(VecTy && VecTy->getScalarType()->isIntegerTy() &&do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5754 | VecTy->getScalarSizeInBits() >= 8,do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5755 | "experimental_stepvector only supported for vectors of integers "do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5756 | "with a bitwidth of at least 8.",do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false) | ||||
| 5757 | &Call)do { if (!(VecTy && VecTy->getScalarType()->isIntegerTy () && VecTy->getScalarSizeInBits() >= 8)) { CheckFailed ("experimental_stepvector only supported for vectors of integers " "with a bitwidth of at least 8.", &Call); return; } } while (false); | ||||
| 5758 | break; | ||||
| 5759 | } | ||||
| 5760 | case Intrinsic::vector_insert: { | ||||
| 5761 | Value *Vec = Call.getArgOperand(0); | ||||
| 5762 | Value *SubVec = Call.getArgOperand(1); | ||||
| 5763 | Value *Idx = Call.getArgOperand(2); | ||||
| 5764 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
| 5765 | |||||
| 5766 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
| 5767 | VectorType *SubVecTy = cast<VectorType>(SubVec->getType()); | ||||
| 5768 | |||||
| 5769 | ElementCount VecEC = VecTy->getElementCount(); | ||||
| 5770 | ElementCount SubVecEC = SubVecTy->getElementCount(); | ||||
| 5771 | Check(VecTy->getElementType() == SubVecTy->getElementType(),do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5772 | "vector_insert parameters must have the same element "do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5773 | "type.",do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false) | ||||
| 5774 | &Call)do { if (!(VecTy->getElementType() == SubVecTy->getElementType ())) { CheckFailed("vector_insert parameters must have the same element " "type.", &Call); return; } } while (false); | ||||
| 5775 | Check(IdxN % SubVecEC.getKnownMinValue() == 0,do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false) | ||||
| 5776 | "vector_insert index must be a constant multiple of "do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false) | ||||
| 5777 | "the subvector's known minimum vector length.")do { if (!(IdxN % SubVecEC.getKnownMinValue() == 0)) { CheckFailed ("vector_insert index must be a constant multiple of " "the subvector's known minimum vector length." ); return; } } while (false); | ||||
| 5778 | |||||
| 5779 | // If this insertion is not the 'mixed' case where a fixed vector is | ||||
| 5780 | // inserted into a scalable vector, ensure that the insertion of the | ||||
| 5781 | // subvector does not overrun the parent vector. | ||||
| 5782 | if (VecEC.isScalable() == SubVecEC.isScalable()) { | ||||
| 5783 | Check(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5784 | IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5785 | "subvector operand of vector_insert would overrun the "do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false) | ||||
| 5786 | "vector being inserted into.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + SubVecEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("subvector operand of vector_insert would overrun the " "vector being inserted into."); return; } } while (false); | ||||
| 5787 | } | ||||
| 5788 | break; | ||||
| 5789 | } | ||||
| 5790 | case Intrinsic::vector_extract: { | ||||
| 5791 | Value *Vec = Call.getArgOperand(0); | ||||
| 5792 | Value *Idx = Call.getArgOperand(1); | ||||
| 5793 | unsigned IdxN = cast<ConstantInt>(Idx)->getZExtValue(); | ||||
| 5794 | |||||
| 5795 | VectorType *ResultTy = cast<VectorType>(Call.getType()); | ||||
| 5796 | VectorType *VecTy = cast<VectorType>(Vec->getType()); | ||||
| 5797 | |||||
| 5798 | ElementCount VecEC = VecTy->getElementCount(); | ||||
| 5799 | ElementCount ResultEC = ResultTy->getElementCount(); | ||||
| 5800 | |||||
| 5801 | Check(ResultTy->getElementType() == VecTy->getElementType(),do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5802 | "vector_extract result must have the same element "do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5803 | "type as the input vector.",do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false) | ||||
| 5804 | &Call)do { if (!(ResultTy->getElementType() == VecTy->getElementType ())) { CheckFailed("vector_extract result must have the same element " "type as the input vector.", &Call); return; } } while ( false); | ||||
| 5805 | Check(IdxN % ResultEC.getKnownMinValue() == 0,do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false) | ||||
| 5806 | "vector_extract index must be a constant multiple of "do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false) | ||||
| 5807 | "the result type's known minimum vector length.")do { if (!(IdxN % ResultEC.getKnownMinValue() == 0)) { CheckFailed ("vector_extract index must be a constant multiple of " "the result type's known minimum vector length." ); return; } } while (false); | ||||
| 5808 | |||||
| 5809 | // If this extraction is not the 'mixed' case where a fixed vector is is | ||||
| 5810 | // extracted from a scalable vector, ensure that the extraction does not | ||||
| 5811 | // overrun the parent vector. | ||||
| 5812 | if (VecEC.isScalable() == ResultEC.isScalable()) { | ||||
| 5813 | Check(IdxN < VecEC.getKnownMinValue() &&do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false) | ||||
| 5814 | IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue(),do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false) | ||||
| 5815 | "vector_extract would overrun.")do { if (!(IdxN < VecEC.getKnownMinValue() && IdxN + ResultEC.getKnownMinValue() <= VecEC.getKnownMinValue() )) { CheckFailed("vector_extract would overrun."); return; } } while (false); | ||||
| 5816 | } | ||||
| 5817 | break; | ||||
| 5818 | } | ||||
| 5819 | case Intrinsic::experimental_noalias_scope_decl: { | ||||
| 5820 | NoAliasScopeDecls.push_back(cast<IntrinsicInst>(&Call)); | ||||
| 5821 | break; | ||||
| 5822 | } | ||||
| 5823 | case Intrinsic::preserve_array_access_index: | ||||
| 5824 | case Intrinsic::preserve_struct_access_index: | ||||
| 5825 | case Intrinsic::aarch64_ldaxr: | ||||
| 5826 | case Intrinsic::aarch64_ldxr: | ||||
| 5827 | case Intrinsic::arm_ldaex: | ||||
| 5828 | case Intrinsic::arm_ldrex: { | ||||
| 5829 | Type *ElemTy = Call.getParamElementType(0); | ||||
| 5830 | Check(ElemTy, "Intrinsic requires elementtype attribute on first argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false) | ||||
| 5831 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on first argument." , &Call); return; } } while (false); | ||||
| 5832 | break; | ||||
| 5833 | } | ||||
| 5834 | case Intrinsic::aarch64_stlxr: | ||||
| 5835 | case Intrinsic::aarch64_stxr: | ||||
| 5836 | case Intrinsic::arm_stlex: | ||||
| 5837 | case Intrinsic::arm_strex: { | ||||
| 5838 | Type *ElemTy = Call.getAttributes().getParamElementType(1); | ||||
| 5839 | Check(ElemTy,do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false) | ||||
| 5840 | "Intrinsic requires elementtype attribute on second argument.",do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false) | ||||
| 5841 | &Call)do { if (!(ElemTy)) { CheckFailed("Intrinsic requires elementtype attribute on second argument." , &Call); return; } } while (false); | ||||
| 5842 | break; | ||||
| 5843 | } | ||||
| 5844 | case Intrinsic::aarch64_prefetch: { | ||||
| 5845 | Check(cast<ConstantInt>(Call.getArgOperand(1))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("write argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
| 5846 | "write argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(1))-> getZExtValue() < 2)) { CheckFailed("write argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
| 5847 | Check(cast<ConstantInt>(Call.getArgOperand(2))->getZExtValue() < 4,do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("target argument to llvm.aarch64.prefetch must be 0-3" , Call); return; } } while (false) | ||||
| 5848 | "target argument to llvm.aarch64.prefetch must be 0-3", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(2))-> getZExtValue() < 4)) { CheckFailed("target argument to llvm.aarch64.prefetch must be 0-3" , Call); return; } } while (false); | ||||
| 5849 | Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("stream argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
| 5850 | "stream argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(3))-> getZExtValue() < 2)) { CheckFailed("stream argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
| 5851 | Check(cast<ConstantInt>(Call.getArgOperand(4))->getZExtValue() < 2,do { if (!(cast<ConstantInt>(Call.getArgOperand(4))-> getZExtValue() < 2)) { CheckFailed("isdata argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false) | ||||
| 5852 | "isdata argument to llvm.aarch64.prefetch must be 0 or 1", Call)do { if (!(cast<ConstantInt>(Call.getArgOperand(4))-> getZExtValue() < 2)) { CheckFailed("isdata argument to llvm.aarch64.prefetch must be 0 or 1" , Call); return; } } while (false); | ||||
| 5853 | break; | ||||
| 5854 | } | ||||
| 5855 | case Intrinsic::callbr_landingpad: { | ||||
| 5856 | const auto *CBR = dyn_cast<CallBrInst>(Call.getOperand(0)); | ||||
| 5857 | Check(CBR, "intrinstic requires callbr operand", &Call)do { if (!(CBR)) { CheckFailed("intrinstic requires callbr operand" , &Call); return; } } while (false); | ||||
| 5858 | if (!CBR) | ||||
| 5859 | break; | ||||
| 5860 | |||||
| 5861 | const BasicBlock *LandingPadBB = Call.getParent(); | ||||
| 5862 | const BasicBlock *PredBB = LandingPadBB->getUniquePredecessor(); | ||||
| 5863 | if (!PredBB) { | ||||
| 5864 | CheckFailed("Intrinsic in block must have 1 unique predecessor", &Call); | ||||
| 5865 | break; | ||||
| 5866 | } | ||||
| 5867 | if (!isa<CallBrInst>(PredBB->getTerminator())) { | ||||
| 5868 | CheckFailed("Intrinsic must have corresponding callbr in predecessor", | ||||
| 5869 | &Call); | ||||
| 5870 | break; | ||||
| 5871 | } | ||||
| 5872 | Check(llvm::any_of(CBR->getIndirectDests(),do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5873 | [LandingPadBB](const BasicBlock *IndDest) {do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5874 | return IndDest == LandingPadBB;do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5875 | }),do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5876 | "Intrinsic's corresponding callbr must have intrinsic's parent basic "do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5877 | "block in indirect destination list",do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false) | ||||
| 5878 | &Call)do { if (!(llvm::any_of(CBR->getIndirectDests(), [LandingPadBB ](const BasicBlock *IndDest) { return IndDest == LandingPadBB ; }))) { CheckFailed("Intrinsic's corresponding callbr must have intrinsic's parent basic " "block in indirect destination list", &Call); return; } } while (false); | ||||
| 5879 | const Instruction &First = *LandingPadBB->begin(); | ||||
| 5880 | Check(&First == &Call, "No other instructions may proceed intrinsic",do { if (!(&First == &Call)) { CheckFailed("No other instructions may proceed intrinsic" , &Call); return; } } while (false) | ||||
| 5881 | &Call)do { if (!(&First == &Call)) { CheckFailed("No other instructions may proceed intrinsic" , &Call); return; } } while (false); | ||||
| 5882 | break; | ||||
| 5883 | } | ||||
| 5884 | }; | ||||
| 5885 | |||||
| 5886 | // Verify that there aren't any unmediated control transfers between funclets. | ||||
| 5887 | if (IntrinsicInst::mayLowerToFunctionCall(ID)) { | ||||
| 5888 | Function *F = Call.getParent()->getParent(); | ||||
| 5889 | if (F->hasPersonalityFn() && | ||||
| 5890 | isScopedEHPersonality(classifyEHPersonality(F->getPersonalityFn()))) { | ||||
| 5891 | // Run EH funclet coloring on-demand and cache results for other intrinsic | ||||
| 5892 | // calls in this function | ||||
| 5893 | if (BlockEHFuncletColors.empty()) | ||||
| 5894 | BlockEHFuncletColors = colorEHFunclets(*F); | ||||
| 5895 | |||||
| 5896 | // Check for catch-/cleanup-pad in first funclet block | ||||
| 5897 | bool InEHFunclet = false; | ||||
| 5898 | BasicBlock *CallBB = Call.getParent(); | ||||
| 5899 | const ColorVector &CV = BlockEHFuncletColors.find(CallBB)->second; | ||||
| 5900 | assert(CV.size() > 0 && "Uncolored block")(static_cast <bool> (CV.size() > 0 && "Uncolored block" ) ? void (0) : __assert_fail ("CV.size() > 0 && \"Uncolored block\"" , "llvm/lib/IR/Verifier.cpp", 5900, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 5901 | for (BasicBlock *ColorFirstBB : CV) | ||||
| 5902 | if (dyn_cast_or_null<FuncletPadInst>(ColorFirstBB->getFirstNonPHI())) | ||||
| 5903 | InEHFunclet = true; | ||||
| 5904 | |||||
| 5905 | // Check for funclet operand bundle | ||||
| 5906 | bool HasToken = false; | ||||
| 5907 | for (unsigned I = 0, E = Call.getNumOperandBundles(); I != E; ++I) | ||||
| 5908 | if (Call.getOperandBundleAt(I).getTagID() == LLVMContext::OB_funclet) | ||||
| 5909 | HasToken = true; | ||||
| 5910 | |||||
| 5911 | // This would cause silent code truncation in WinEHPrepare | ||||
| 5912 | if (InEHFunclet) | ||||
| 5913 | Check(HasToken, "Missing funclet token on intrinsic call", &Call)do { if (!(HasToken)) { CheckFailed("Missing funclet token on intrinsic call" , &Call); return; } } while (false); | ||||
| 5914 | } | ||||
| 5915 | } | ||||
| 5916 | } | ||||
| 5917 | |||||
| 5918 | /// Carefully grab the subprogram from a local scope. | ||||
| 5919 | /// | ||||
| 5920 | /// This carefully grabs the subprogram from a local scope, avoiding the | ||||
| 5921 | /// built-in assertions that would typically fire. | ||||
| 5922 | static DISubprogram *getSubprogram(Metadata *LocalScope) { | ||||
| 5923 | if (!LocalScope) | ||||
| 5924 | return nullptr; | ||||
| 5925 | |||||
| 5926 | if (auto *SP = dyn_cast<DISubprogram>(LocalScope)) | ||||
| 5927 | return SP; | ||||
| 5928 | |||||
| 5929 | if (auto *LB = dyn_cast<DILexicalBlockBase>(LocalScope)) | ||||
| 5930 | return getSubprogram(LB->getRawScope()); | ||||
| 5931 | |||||
| 5932 | // Just return null; broken scope chains are checked elsewhere. | ||||
| 5933 | assert(!isa<DILocalScope>(LocalScope) && "Unknown type of local scope")(static_cast <bool> (!isa<DILocalScope>(LocalScope ) && "Unknown type of local scope") ? void (0) : __assert_fail ("!isa<DILocalScope>(LocalScope) && \"Unknown type of local scope\"" , "llvm/lib/IR/Verifier.cpp", 5933, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 5934 | return nullptr; | ||||
| 5935 | } | ||||
| 5936 | |||||
| 5937 | void Verifier::visitVPIntrinsic(VPIntrinsic &VPI) { | ||||
| 5938 | if (auto *VPCast = dyn_cast<VPCastIntrinsic>(&VPI)) { | ||||
| 5939 | auto *RetTy = cast<VectorType>(VPCast->getType()); | ||||
| 5940 | auto *ValTy = cast<VectorType>(VPCast->getOperand(0)->getType()); | ||||
| 5941 | Check(RetTy->getElementCount() == ValTy->getElementCount(),do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
| 5942 | "VP cast intrinsic first argument and result vector lengths must be "do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
| 5943 | "equal",do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false) | ||||
| 5944 | *VPCast)do { if (!(RetTy->getElementCount() == ValTy->getElementCount ())) { CheckFailed("VP cast intrinsic first argument and result vector lengths must be " "equal", *VPCast); return; } } while (false); | ||||
| 5945 | |||||
| 5946 | switch (VPCast->getIntrinsicID()) { | ||||
| 5947 | default: | ||||
| 5948 | llvm_unreachable("Unknown VP cast intrinsic")::llvm::llvm_unreachable_internal("Unknown VP cast intrinsic" , "llvm/lib/IR/Verifier.cpp", 5948); | ||||
| 5949 | case Intrinsic::vp_trunc: | ||||
| 5950 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
| 5951 | "llvm.vp.trunc intrinsic first argument and result element type "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
| 5952 | "must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false) | ||||
| 5953 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.trunc intrinsic first argument and result element type " "must be integer", *VPCast); return; } } while (false); | ||||
| 5954 | Check(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5955 | "llvm.vp.trunc intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5956 | "larger than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5957 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.trunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
| 5958 | break; | ||||
| 5959 | case Intrinsic::vp_zext: | ||||
| 5960 | case Intrinsic::vp_sext: | ||||
| 5961 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
| 5962 | "llvm.vp.zext or llvm.vp.sext intrinsic first argument and result "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
| 5963 | "element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false) | ||||
| 5964 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic first argument and result " "element type must be integer", *VPCast); return; } } while ( false); | ||||
| 5965 | Check(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
| 5966 | "llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first "do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
| 5967 | "argument must be smaller than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false) | ||||
| 5968 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.zext or llvm.vp.sext intrinsic the bit size of first " "argument must be smaller than the bit size of the return type" , *VPCast); return; } } while (false); | ||||
| 5969 | break; | ||||
| 5970 | case Intrinsic::vp_fptoui: | ||||
| 5971 | case Intrinsic::vp_fptosi: | ||||
| 5972 | Check(do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
| 5973 | RetTy->isIntOrIntVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
| 5974 | "llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
| 5975 | "type must be floating-point and result element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false) | ||||
| 5976 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptoui or llvm.vp.fptosi intrinsic first argument element " "type must be floating-point and result element type must be integer" , *VPCast); return; } } while (false); | ||||
| 5977 | break; | ||||
| 5978 | case Intrinsic::vp_uitofp: | ||||
| 5979 | case Intrinsic::vp_sitofp: | ||||
| 5980 | Check(do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
| 5981 | RetTy->isFPOrFPVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
| 5982 | "llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
| 5983 | "type must be integer and result element type must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false) | ||||
| 5984 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.uitofp or llvm.vp.sitofp intrinsic first argument element " "type must be integer and result element type must be floating-point" , *VPCast); return; } } while (false); | ||||
| 5985 | break; | ||||
| 5986 | case Intrinsic::vp_fptrunc: | ||||
| 5987 | Check(RetTy->isFPOrFPVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 5988 | "llvm.vp.fptrunc intrinsic first argument and result element type "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 5989 | "must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 5990 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fptrunc intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ); | ||||
| 5991 | Check(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5992 | "llvm.vp.fptrunc intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5993 | "larger than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 5994 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() < ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fptrunc intrinsic the bit size of first argument must be " "larger than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
| 5995 | break; | ||||
| 5996 | case Intrinsic::vp_fpext: | ||||
| 5997 | Check(RetTy->isFPOrFPVectorTy() && ValTy->isFPOrFPVectorTy(),do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 5998 | "llvm.vp.fpext intrinsic first argument and result element type "do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 5999 | "must be floating-point",do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ) | ||||
| 6000 | *VPCast)do { if (!(RetTy->isFPOrFPVectorTy() && ValTy-> isFPOrFPVectorTy())) { CheckFailed("llvm.vp.fpext intrinsic first argument and result element type " "must be floating-point", *VPCast); return; } } while (false ); | ||||
| 6001 | Check(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits(),do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 6002 | "llvm.vp.fpext intrinsic the bit size of first argument must be "do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 6003 | "smaller than the bit size of the return type",do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false) | ||||
| 6004 | *VPCast)do { if (!(RetTy->getScalarSizeInBits() > ValTy->getScalarSizeInBits ())) { CheckFailed("llvm.vp.fpext intrinsic the bit size of first argument must be " "smaller than the bit size of the return type", *VPCast); return ; } } while (false); | ||||
| 6005 | break; | ||||
| 6006 | case Intrinsic::vp_ptrtoint: | ||||
| 6007 | Check(RetTy->isIntOrIntVectorTy() && ValTy->isPtrOrPtrVectorTy(),do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
| 6008 | "llvm.vp.ptrtoint intrinsic first argument element type must be "do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
| 6009 | "pointer and result element type must be integer",do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false) | ||||
| 6010 | *VPCast)do { if (!(RetTy->isIntOrIntVectorTy() && ValTy-> isPtrOrPtrVectorTy())) { CheckFailed("llvm.vp.ptrtoint intrinsic first argument element type must be " "pointer and result element type must be integer", *VPCast); return; } } while (false); | ||||
| 6011 | break; | ||||
| 6012 | case Intrinsic::vp_inttoptr: | ||||
| 6013 | Check(RetTy->isPtrOrPtrVectorTy() && ValTy->isIntOrIntVectorTy(),do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
| 6014 | "llvm.vp.inttoptr intrinsic first argument element type must be "do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
| 6015 | "integer and result element type must be pointer",do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false) | ||||
| 6016 | *VPCast)do { if (!(RetTy->isPtrOrPtrVectorTy() && ValTy-> isIntOrIntVectorTy())) { CheckFailed("llvm.vp.inttoptr intrinsic first argument element type must be " "integer and result element type must be pointer", *VPCast); return; } } while (false); | ||||
| 6017 | break; | ||||
| 6018 | } | ||||
| 6019 | } | ||||
| 6020 | if (VPI.getIntrinsicID() == Intrinsic::vp_fcmp) { | ||||
| 6021 | auto Pred = cast<VPCmpIntrinsic>(&VPI)->getPredicate(); | ||||
| 6022 | Check(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for VP FP comparison intrinsic" , &VPI); return; } } while (false) | ||||
| 6023 | "invalid predicate for VP FP comparison intrinsic", &VPI)do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for VP FP comparison intrinsic" , &VPI); return; } } while (false); | ||||
| 6024 | } | ||||
| 6025 | if (VPI.getIntrinsicID() == Intrinsic::vp_icmp) { | ||||
| 6026 | auto Pred = cast<VPCmpIntrinsic>(&VPI)->getPredicate(); | ||||
| 6027 | Check(CmpInst::isIntPredicate(Pred),do { if (!(CmpInst::isIntPredicate(Pred))) { CheckFailed("invalid predicate for VP integer comparison intrinsic" , &VPI); return; } } while (false) | ||||
| 6028 | "invalid predicate for VP integer comparison intrinsic", &VPI)do { if (!(CmpInst::isIntPredicate(Pred))) { CheckFailed("invalid predicate for VP integer comparison intrinsic" , &VPI); return; } } while (false); | ||||
| 6029 | } | ||||
| 6030 | } | ||||
| 6031 | |||||
| 6032 | void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { | ||||
| 6033 | unsigned NumOperands; | ||||
| 6034 | bool HasRoundingMD; | ||||
| 6035 | switch (FPI.getIntrinsicID()) { | ||||
| 6036 | #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ | ||||
| 6037 | case Intrinsic::INTRINSIC: \ | ||||
| 6038 | NumOperands = NARG; \ | ||||
| 6039 | HasRoundingMD = ROUND_MODE; \ | ||||
| 6040 | break; | ||||
| 6041 | #include "llvm/IR/ConstrainedOps.def" | ||||
| 6042 | default: | ||||
| 6043 | llvm_unreachable("Invalid constrained FP intrinsic!")::llvm::llvm_unreachable_internal("Invalid constrained FP intrinsic!" , "llvm/lib/IR/Verifier.cpp", 6043); | ||||
| 6044 | } | ||||
| 6045 | NumOperands += (1 + HasRoundingMD); | ||||
| 6046 | // Compare intrinsics carry an extra predicate metadata operand. | ||||
| 6047 | if (isa<ConstrainedFPCmpIntrinsic>(FPI)) | ||||
| 6048 | NumOperands += 1; | ||||
| 6049 | Check((FPI.arg_size() == NumOperands),do { if (!((FPI.arg_size() == NumOperands))) { CheckFailed("invalid arguments for constrained FP intrinsic" , &FPI); return; } } while (false) | ||||
| 6050 | "invalid arguments for constrained FP intrinsic", &FPI)do { if (!((FPI.arg_size() == NumOperands))) { CheckFailed("invalid arguments for constrained FP intrinsic" , &FPI); return; } } while (false); | ||||
| 6051 | |||||
| 6052 | switch (FPI.getIntrinsicID()) { | ||||
| 6053 | case Intrinsic::experimental_constrained_lrint: | ||||
| 6054 | case Intrinsic::experimental_constrained_llrint: { | ||||
| 6055 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
| 6056 | Type *ResultTy = FPI.getType(); | ||||
| 6057 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
| 6058 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
| 6059 | } | ||||
| 6060 | break; | ||||
| 6061 | |||||
| 6062 | case Intrinsic::experimental_constrained_lround: | ||||
| 6063 | case Intrinsic::experimental_constrained_llround: { | ||||
| 6064 | Type *ValTy = FPI.getArgOperand(0)->getType(); | ||||
| 6065 | Type *ResultTy = FPI.getType(); | ||||
| 6066 | Check(!ValTy->isVectorTy() && !ResultTy->isVectorTy(),do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false) | ||||
| 6067 | "Intrinsic does not support vectors", &FPI)do { if (!(!ValTy->isVectorTy() && !ResultTy->isVectorTy ())) { CheckFailed("Intrinsic does not support vectors", & FPI); return; } } while (false); | ||||
| 6068 | break; | ||||
| 6069 | } | ||||
| 6070 | |||||
| 6071 | case Intrinsic::experimental_constrained_fcmp: | ||||
| 6072 | case Intrinsic::experimental_constrained_fcmps: { | ||||
| 6073 | auto Pred = cast<ConstrainedFPCmpIntrinsic>(&FPI)->getPredicate(); | ||||
| 6074 | Check(CmpInst::isFPPredicate(Pred),do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false) | ||||
| 6075 | "invalid predicate for constrained FP comparison intrinsic", &FPI)do { if (!(CmpInst::isFPPredicate(Pred))) { CheckFailed("invalid predicate for constrained FP comparison intrinsic" , &FPI); return; } } while (false); | ||||
| 6076 | break; | ||||
| 6077 | } | ||||
| 6078 | |||||
| 6079 | case Intrinsic::experimental_constrained_fptosi: | ||||
| 6080 | case Intrinsic::experimental_constrained_fptoui: { | ||||
| 6081 | Value *Operand = FPI.getArgOperand(0); | ||||
| 6082 | ElementCount SrcEC; | ||||
| 6083 | Check(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false) | ||||
| 6084 | "Intrinsic first argument must be floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic first argument must be floating point", &FPI) ; return; } } while (false); | ||||
| 6085 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 6086 | SrcEC = cast<VectorType>(OperandT)->getElementCount(); | ||||
| 6087 | } | ||||
| 6088 | |||||
| 6089 | Operand = &FPI; | ||||
| 6090 | Check(SrcEC.isNonZero() == Operand->getType()->isVectorTy(),do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 6091 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 6092 | Check(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false) | ||||
| 6093 | "Intrinsic result must be an integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic result must be an integer", &FPI) ; return; } } while (false); | ||||
| 6094 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 6095 | Check(SrcEC == cast<VectorType>(OperandT)->getElementCount(),do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6096 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6097 | &FPI)do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 6098 | } | ||||
| 6099 | } | ||||
| 6100 | break; | ||||
| 6101 | |||||
| 6102 | case Intrinsic::experimental_constrained_sitofp: | ||||
| 6103 | case Intrinsic::experimental_constrained_uitofp: { | ||||
| 6104 | Value *Operand = FPI.getArgOperand(0); | ||||
| 6105 | ElementCount SrcEC; | ||||
| 6106 | Check(Operand->getType()->isIntOrIntVectorTy(),do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false) | ||||
| 6107 | "Intrinsic first argument must be integer", &FPI)do { if (!(Operand->getType()->isIntOrIntVectorTy())) { CheckFailed("Intrinsic first argument must be integer", & FPI); return; } } while (false); | ||||
| 6108 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 6109 | SrcEC = cast<VectorType>(OperandT)->getElementCount(); | ||||
| 6110 | } | ||||
| 6111 | |||||
| 6112 | Operand = &FPI; | ||||
| 6113 | Check(SrcEC.isNonZero() == Operand->getType()->isVectorTy(),do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 6114 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(SrcEC.isNonZero() == Operand->getType()->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 6115 | Check(Operand->getType()->isFPOrFPVectorTy(),do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false) | ||||
| 6116 | "Intrinsic result must be a floating point", &FPI)do { if (!(Operand->getType()->isFPOrFPVectorTy())) { CheckFailed ("Intrinsic result must be a floating point", &FPI); return ; } } while (false); | ||||
| 6117 | if (auto *OperandT = dyn_cast<VectorType>(Operand->getType())) { | ||||
| 6118 | Check(SrcEC == cast<VectorType>(OperandT)->getElementCount(),do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6119 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6120 | &FPI)do { if (!(SrcEC == cast<VectorType>(OperandT)->getElementCount ())) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 6121 | } | ||||
| 6122 | } break; | ||||
| 6123 | |||||
| 6124 | case Intrinsic::experimental_constrained_fptrunc: | ||||
| 6125 | case Intrinsic::experimental_constrained_fpext: { | ||||
| 6126 | Value *Operand = FPI.getArgOperand(0); | ||||
| 6127 | Type *OperandTy = Operand->getType(); | ||||
| 6128 | Value *Result = &FPI; | ||||
| 6129 | Type *ResultTy = Result->getType(); | ||||
| 6130 | Check(OperandTy->isFPOrFPVectorTy(),do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false) | ||||
| 6131 | "Intrinsic first argument must be FP or FP vector", &FPI)do { if (!(OperandTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic first argument must be FP or FP vector" , &FPI); return; } } while (false); | ||||
| 6132 | Check(ResultTy->isFPOrFPVectorTy(),do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false) | ||||
| 6133 | "Intrinsic result must be FP or FP vector", &FPI)do { if (!(ResultTy->isFPOrFPVectorTy())) { CheckFailed("Intrinsic result must be FP or FP vector" , &FPI); return; } } while (false); | ||||
| 6134 | Check(OperandTy->isVectorTy() == ResultTy->isVectorTy(),do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false) | ||||
| 6135 | "Intrinsic first argument and result disagree on vector use", &FPI)do { if (!(OperandTy->isVectorTy() == ResultTy->isVectorTy ())) { CheckFailed("Intrinsic first argument and result disagree on vector use" , &FPI); return; } } while (false); | ||||
| 6136 | if (OperandTy->isVectorTy()) { | ||||
| 6137 | Check(cast<VectorType>(OperandTy)->getElementCount() ==do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6138 | cast<VectorType>(ResultTy)->getElementCount(),do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6139 | "Intrinsic first argument and result vector lengths must be equal",do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false) | ||||
| 6140 | &FPI)do { if (!(cast<VectorType>(OperandTy)->getElementCount () == cast<VectorType>(ResultTy)->getElementCount()) ) { CheckFailed("Intrinsic first argument and result vector lengths must be equal" , &FPI); return; } } while (false); | ||||
| 6141 | } | ||||
| 6142 | if (FPI.getIntrinsicID() == Intrinsic::experimental_constrained_fptrunc) { | ||||
| 6143 | Check(OperandTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
| 6144 | "Intrinsic first argument's type must be larger than result type",do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false) | ||||
| 6145 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() > ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be larger than result type" , &FPI); return; } } while (false); | ||||
| 6146 | } else { | ||||
| 6147 | Check(OperandTy->getScalarSizeInBits() < ResultTy->getScalarSizeInBits(),do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
| 6148 | "Intrinsic first argument's type must be smaller than result type",do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false) | ||||
| 6149 | &FPI)do { if (!(OperandTy->getScalarSizeInBits() < ResultTy-> getScalarSizeInBits())) { CheckFailed("Intrinsic first argument's type must be smaller than result type" , &FPI); return; } } while (false); | ||||
| 6150 | } | ||||
| 6151 | } | ||||
| 6152 | break; | ||||
| 6153 | |||||
| 6154 | default: | ||||
| 6155 | break; | ||||
| 6156 | } | ||||
| 6157 | |||||
| 6158 | // If a non-metadata argument is passed in a metadata slot then the | ||||
| 6159 | // error will be caught earlier when the incorrect argument doesn't | ||||
| 6160 | // match the specification in the intrinsic call table. Thus, no | ||||
| 6161 | // argument type check is needed here. | ||||
| 6162 | |||||
| 6163 | Check(FPI.getExceptionBehavior().has_value(),do { if (!(FPI.getExceptionBehavior().has_value())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false) | ||||
| 6164 | "invalid exception behavior argument", &FPI)do { if (!(FPI.getExceptionBehavior().has_value())) { CheckFailed ("invalid exception behavior argument", &FPI); return; } } while (false); | ||||
| 6165 | if (HasRoundingMD) { | ||||
| 6166 | Check(FPI.getRoundingMode().has_value(), "invalid rounding mode argument",do { if (!(FPI.getRoundingMode().has_value())) { CheckFailed( "invalid rounding mode argument", &FPI); return; } } while (false) | ||||
| 6167 | &FPI)do { if (!(FPI.getRoundingMode().has_value())) { CheckFailed( "invalid rounding mode argument", &FPI); return; } } while (false); | ||||
| 6168 | } | ||||
| 6169 | } | ||||
| 6170 | |||||
| 6171 | void Verifier::visitDbgIntrinsic(StringRef Kind, DbgVariableIntrinsic &DII) { | ||||
| 6172 | auto *MD = DII.getRawLocation(); | ||||
| 6173 | CheckDI(isa<ValueAsMetadata>(MD) || isa<DIArgList>(MD) ||do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
| 6174 | (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()),do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false) | ||||
| 6175 | "invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD)do { if (!(isa<ValueAsMetadata>(MD) || isa<DIArgList >(MD) || (isa<MDNode>(MD) && !cast<MDNode >(MD)->getNumOperands()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic address/value", &DII, MD); return; } } while (false); | ||||
| 6176 | CheckDI(isa<DILocalVariable>(DII.getRawVariable()),do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
| 6177 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DII,do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false) | ||||
| 6178 | DII.getRawVariable())do { if (!(isa<DILocalVariable>(DII.getRawVariable()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic variable" , &DII, DII.getRawVariable()); return; } } while (false); | ||||
| 6179 | CheckDI(isa<DIExpression>(DII.getRawExpression()),do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
| 6180 | "invalid llvm.dbg." + Kind + " intrinsic expression", &DII,do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ) | ||||
| 6181 | DII.getRawExpression())do { if (!(isa<DIExpression>(DII.getRawExpression()))) { DebugInfoCheckFailed("invalid llvm.dbg." + Kind + " intrinsic expression" , &DII, DII.getRawExpression()); return; } } while (false ); | ||||
| 6182 | |||||
| 6183 | if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&DII)) { | ||||
| 6184 | CheckDI(isa<DIAssignID>(DAI->getRawAssignID()),do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ) | ||||
| 6185 | "invalid llvm.dbg.assign intrinsic DIAssignID", &DII,do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ) | ||||
| 6186 | DAI->getRawAssignID())do { if (!(isa<DIAssignID>(DAI->getRawAssignID()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic DIAssignID" , &DII, DAI->getRawAssignID()); return; } } while (false ); | ||||
| 6187 | const auto *RawAddr = DAI->getRawAddress(); | ||||
| 6188 | CheckDI(do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
| 6189 | isa<ValueAsMetadata>(RawAddr) ||do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
| 6190 | (isa<MDNode>(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands()),do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
| 6191 | "invalid llvm.dbg.assign intrinsic address", &DII,do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ) | ||||
| 6192 | DAI->getRawAddress())do { if (!(isa<ValueAsMetadata>(RawAddr) || (isa<MDNode >(RawAddr) && !cast<MDNode>(RawAddr)->getNumOperands ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address" , &DII, DAI->getRawAddress()); return; } } while (false ); | ||||
| 6193 | CheckDI(isa<DIExpression>(DAI->getRawAddressExpression()),do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false) | ||||
| 6194 | "invalid llvm.dbg.assign intrinsic address expression", &DII,do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false) | ||||
| 6195 | DAI->getRawAddressExpression())do { if (!(isa<DIExpression>(DAI->getRawAddressExpression ()))) { DebugInfoCheckFailed("invalid llvm.dbg.assign intrinsic address expression" , &DII, DAI->getRawAddressExpression()); return; } } while (false); | ||||
| 6196 | // All of the linked instructions should be in the same function as DII. | ||||
| 6197 | for (Instruction *I : at::getAssignmentInsts(DAI)) | ||||
| 6198 | CheckDI(DAI->getFunction() == I->getFunction(),do { if (!(DAI->getFunction() == I->getFunction())) { DebugInfoCheckFailed ("inst not in same function as dbg.assign", I, DAI); return; } } while (false) | ||||
| 6199 | "inst not in same function as dbg.assign", I, DAI)do { if (!(DAI->getFunction() == I->getFunction())) { DebugInfoCheckFailed ("inst not in same function as dbg.assign", I, DAI); return; } } while (false); | ||||
| 6200 | } | ||||
| 6201 | |||||
| 6202 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
| 6203 | if (MDNode *N = DII.getDebugLoc().getAsMDNode()) | ||||
| 6204 | if (!isa<DILocation>(N)) | ||||
| 6205 | return; | ||||
| 6206 | |||||
| 6207 | BasicBlock *BB = DII.getParent(); | ||||
| 6208 | Function *F = BB ? BB->getParent() : nullptr; | ||||
| 6209 | |||||
| 6210 | // The scopes for variables and !dbg attachments must agree. | ||||
| 6211 | DILocalVariable *Var = DII.getVariable(); | ||||
| 6212 | DILocation *Loc = DII.getDebugLoc(); | ||||
| 6213 | CheckDI(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment",do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false) | ||||
| 6214 | &DII, BB, F)do { if (!(Loc)) { DebugInfoCheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DII, BB, F); return; } } while (false); | ||||
| 6215 | |||||
| 6216 | DISubprogram *VarSP = getSubprogram(Var->getRawScope()); | ||||
| 6217 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
| 6218 | if (!VarSP || !LocSP) | ||||
| 6219 | return; // Broken scope chains are checked elsewhere. | ||||
| 6220 | |||||
| 6221 | CheckDI(VarSP == LocSP,do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6222 | "mismatched subprogram between llvm.dbg." + Kind +do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6223 | " variable and !dbg attachment",do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6224 | &DII, BB, F, Var, Var->getScope()->getSubprogram(), Loc,do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6225 | Loc->getScope()->getSubprogram())do { if (!(VarSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " variable and !dbg attachment", &DII, BB, F, Var , Var->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
| 6226 | |||||
| 6227 | // This check is redundant with one in visitLocalVariable(). | ||||
| 6228 | CheckDI(isType(Var->getRawType()), "invalid type ref", Var,do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false) | ||||
| 6229 | Var->getRawType())do { if (!(isType(Var->getRawType()))) { DebugInfoCheckFailed ("invalid type ref", Var, Var->getRawType()); return; } } while (false); | ||||
| 6230 | verifyFnArgs(DII); | ||||
| 6231 | } | ||||
| 6232 | |||||
| 6233 | void Verifier::visitDbgLabelIntrinsic(StringRef Kind, DbgLabelInst &DLI) { | ||||
| 6234 | CheckDI(isa<DILabel>(DLI.getRawLabel()),do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
| 6235 | "invalid llvm.dbg." + Kind + " intrinsic variable", &DLI,do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false) | ||||
| 6236 | DLI.getRawLabel())do { if (!(isa<DILabel>(DLI.getRawLabel()))) { DebugInfoCheckFailed ("invalid llvm.dbg." + Kind + " intrinsic variable", &DLI , DLI.getRawLabel()); return; } } while (false); | ||||
| 6237 | |||||
| 6238 | // Ignore broken !dbg attachments; they're checked elsewhere. | ||||
| 6239 | if (MDNode *N = DLI.getDebugLoc().getAsMDNode()) | ||||
| 6240 | if (!isa<DILocation>(N)) | ||||
| 6241 | return; | ||||
| 6242 | |||||
| 6243 | BasicBlock *BB = DLI.getParent(); | ||||
| 6244 | Function *F = BB ? BB->getParent() : nullptr; | ||||
| 6245 | |||||
| 6246 | // The scopes for variables and !dbg attachments must agree. | ||||
| 6247 | DILabel *Label = DLI.getLabel(); | ||||
| 6248 | DILocation *Loc = DLI.getDebugLoc(); | ||||
| 6249 | Check(Loc, "llvm.dbg." + Kind + " intrinsic requires a !dbg attachment", &DLI,do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false) | ||||
| 6250 | BB, F)do { if (!(Loc)) { CheckFailed("llvm.dbg." + Kind + " intrinsic requires a !dbg attachment" , &DLI, BB, F); return; } } while (false); | ||||
| 6251 | |||||
| 6252 | DISubprogram *LabelSP = getSubprogram(Label->getRawScope()); | ||||
| 6253 | DISubprogram *LocSP = getSubprogram(Loc->getRawScope()); | ||||
| 6254 | if (!LabelSP || !LocSP) | ||||
| 6255 | return; | ||||
| 6256 | |||||
| 6257 | CheckDI(LabelSP == LocSP,do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6258 | "mismatched subprogram between llvm.dbg." + Kind +do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6259 | " label and !dbg attachment",do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6260 | &DLI, BB, F, Label, Label->getScope()->getSubprogram(), Loc,do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false) | ||||
| 6261 | Loc->getScope()->getSubprogram())do { if (!(LabelSP == LocSP)) { DebugInfoCheckFailed("mismatched subprogram between llvm.dbg." + Kind + " label and !dbg attachment", &DLI, BB, F, Label , Label->getScope()->getSubprogram(), Loc, Loc->getScope ()->getSubprogram()); return; } } while (false); | ||||
| 6262 | } | ||||
| 6263 | |||||
| 6264 | void Verifier::verifyFragmentExpression(const DbgVariableIntrinsic &I) { | ||||
| 6265 | DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); | ||||
| 6266 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
| 6267 | |||||
| 6268 | // We don't know whether this intrinsic verified correctly. | ||||
| 6269 | if (!V || !E || !E->isValid()) | ||||
| 6270 | return; | ||||
| 6271 | |||||
| 6272 | // Nothing to do if this isn't a DW_OP_LLVM_fragment expression. | ||||
| 6273 | auto Fragment = E->getFragmentInfo(); | ||||
| 6274 | if (!Fragment) | ||||
| 6275 | return; | ||||
| 6276 | |||||
| 6277 | // The frontend helps out GDB by emitting the members of local anonymous | ||||
| 6278 | // unions as artificial local variables with shared storage. When SROA splits | ||||
| 6279 | // the storage for artificial local variables that are smaller than the entire | ||||
| 6280 | // union, the overhang piece will be outside of the allotted space for the | ||||
| 6281 | // variable and this check fails. | ||||
| 6282 | // FIXME: Remove this check as soon as clang stops doing this; it hides bugs. | ||||
| 6283 | if (V->isArtificial()) | ||||
| 6284 | return; | ||||
| 6285 | |||||
| 6286 | verifyFragmentExpression(*V, *Fragment, &I); | ||||
| 6287 | } | ||||
| 6288 | |||||
| 6289 | template <typename ValueOrMetadata> | ||||
| 6290 | void Verifier::verifyFragmentExpression(const DIVariable &V, | ||||
| 6291 | DIExpression::FragmentInfo Fragment, | ||||
| 6292 | ValueOrMetadata *Desc) { | ||||
| 6293 | // If there's no size, the type is broken, but that should be checked | ||||
| 6294 | // elsewhere. | ||||
| 6295 | auto VarSize = V.getSizeInBits(); | ||||
| 6296 | if (!VarSize) | ||||
| 6297 | return; | ||||
| 6298 | |||||
| 6299 | unsigned FragSize = Fragment.SizeInBits; | ||||
| 6300 | unsigned FragOffset = Fragment.OffsetInBits; | ||||
| 6301 | CheckDI(FragSize + FragOffset <= *VarSize,do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false) | ||||
| 6302 | "fragment is larger than or outside of variable", Desc, &V)do { if (!(FragSize + FragOffset <= *VarSize)) { DebugInfoCheckFailed ("fragment is larger than or outside of variable", Desc, & V); return; } } while (false); | ||||
| 6303 | CheckDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V)do { if (!(FragSize != *VarSize)) { DebugInfoCheckFailed("fragment covers entire variable" , Desc, &V); return; } } while (false); | ||||
| 6304 | } | ||||
| 6305 | |||||
| 6306 | void Verifier::verifyFnArgs(const DbgVariableIntrinsic &I) { | ||||
| 6307 | // This function does not take the scope of noninlined function arguments into | ||||
| 6308 | // account. Don't run it if current function is nodebug, because it may | ||||
| 6309 | // contain inlined debug intrinsics. | ||||
| 6310 | if (!HasDebugInfo) | ||||
| 6311 | return; | ||||
| 6312 | |||||
| 6313 | // For performance reasons only check non-inlined ones. | ||||
| 6314 | if (I.getDebugLoc()->getInlinedAt()) | ||||
| 6315 | return; | ||||
| 6316 | |||||
| 6317 | DILocalVariable *Var = I.getVariable(); | ||||
| 6318 | CheckDI(Var, "dbg intrinsic without variable")do { if (!(Var)) { DebugInfoCheckFailed("dbg intrinsic without variable" ); return; } } while (false); | ||||
| 6319 | |||||
| 6320 | unsigned ArgNo = Var->getArg(); | ||||
| 6321 | if (!ArgNo) | ||||
| 6322 | return; | ||||
| 6323 | |||||
| 6324 | // Verify there are no duplicate function argument debug info entries. | ||||
| 6325 | // These will cause hard-to-debug assertions in the DWARF backend. | ||||
| 6326 | if (DebugFnArgs.size() < ArgNo) | ||||
| 6327 | DebugFnArgs.resize(ArgNo, nullptr); | ||||
| 6328 | |||||
| 6329 | auto *Prev = DebugFnArgs[ArgNo - 1]; | ||||
| 6330 | DebugFnArgs[ArgNo - 1] = Var; | ||||
| 6331 | CheckDI(!Prev || (Prev == Var), "conflicting debug info for argument", &I,do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false) | ||||
| 6332 | Prev, Var)do { if (!(!Prev || (Prev == Var))) { DebugInfoCheckFailed("conflicting debug info for argument" , &I, Prev, Var); return; } } while (false); | ||||
| 6333 | } | ||||
| 6334 | |||||
| 6335 | void Verifier::verifyNotEntryValue(const DbgVariableIntrinsic &I) { | ||||
| 6336 | DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression()); | ||||
| 6337 | |||||
| 6338 | // We don't know whether this intrinsic verified correctly. | ||||
| 6339 | if (!E || !E->isValid()) | ||||
| 6340 | return; | ||||
| 6341 | |||||
| 6342 | CheckDI(!E->isEntryValue(), "Entry values are only allowed in MIR", &I)do { if (!(!E->isEntryValue())) { DebugInfoCheckFailed("Entry values are only allowed in MIR" , &I); return; } } while (false); | ||||
| 6343 | } | ||||
| 6344 | |||||
| 6345 | void Verifier::verifyCompileUnits() { | ||||
| 6346 | // When more than one Module is imported into the same context, such as during | ||||
| 6347 | // an LTO build before linking the modules, ODR type uniquing may cause types | ||||
| 6348 | // to point to a different CU. This check does not make sense in this case. | ||||
| 6349 | if (M.getContext().isODRUniquingDebugTypes()) | ||||
| 6350 | return; | ||||
| 6351 | auto *CUs = M.getNamedMetadata("llvm.dbg.cu"); | ||||
| 6352 | SmallPtrSet<const Metadata *, 2> Listed; | ||||
| 6353 | if (CUs) | ||||
| 6354 | Listed.insert(CUs->op_begin(), CUs->op_end()); | ||||
| 6355 | for (const auto *CU : CUVisited) | ||||
| 6356 | CheckDI(Listed.count(CU), "DICompileUnit not listed in llvm.dbg.cu", CU)do { if (!(Listed.count(CU))) { DebugInfoCheckFailed("DICompileUnit not listed in llvm.dbg.cu" , CU); return; } } while (false); | ||||
| 6357 | CUVisited.clear(); | ||||
| 6358 | } | ||||
| 6359 | |||||
| 6360 | void Verifier::verifyDeoptimizeCallingConvs() { | ||||
| 6361 | if (DeoptimizeDeclarations.empty()) | ||||
| 6362 | return; | ||||
| 6363 | |||||
| 6364 | const Function *First = DeoptimizeDeclarations[0]; | ||||
| 6365 | for (const auto *F : ArrayRef(DeoptimizeDeclarations).slice(1)) { | ||||
| 6366 | Check(First->getCallingConv() == F->getCallingConv(),do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 6367 | "All llvm.experimental.deoptimize declarations must have the same "do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 6368 | "calling convention",do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false) | ||||
| 6369 | First, F)do { if (!(First->getCallingConv() == F->getCallingConv ())) { CheckFailed("All llvm.experimental.deoptimize declarations must have the same " "calling convention", First, F); return; } } while (false); | ||||
| 6370 | } | ||||
| 6371 | } | ||||
| 6372 | |||||
| 6373 | void Verifier::verifyAttachedCallBundle(const CallBase &Call, | ||||
| 6374 | const OperandBundleUse &BU) { | ||||
| 6375 | FunctionType *FTy = Call.getFunctionType(); | ||||
| 6376 | |||||
| 6377 | Check((FTy->getReturnType()->isPointerTy() ||do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false) | ||||
| 6378 | (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())),do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false) | ||||
| 6379 | "a call with operand bundle \"clang.arc.attachedcall\" must call a "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false) | ||||
| 6380 | "function returning a pointer or a non-returning function that has a "do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false) | ||||
| 6381 | "void return type",do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false) | ||||
| 6382 | Call)do { if (!((FTy->getReturnType()->isPointerTy() || (Call .doesNotReturn() && FTy->getReturnType()->isVoidTy ())))) { CheckFailed("a call with operand bundle \"clang.arc.attachedcall\" must call a " "function returning a pointer or a non-returning function that has a " "void return type", Call); return; } } while (false); | ||||
| 6383 | |||||
| 6384 | Check(BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()),do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
| 6385 | "operand bundle \"clang.arc.attachedcall\" requires one function as "do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
| 6386 | "an argument",do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false) | ||||
| 6387 | Call)do { if (!(BU.Inputs.size() == 1 && isa<Function> (BU.Inputs.front()))) { CheckFailed("operand bundle \"clang.arc.attachedcall\" requires one function as " "an argument", Call); return; } } while (false); | ||||
| 6388 | |||||
| 6389 | auto *Fn = cast<Function>(BU.Inputs.front()); | ||||
| 6390 | Intrinsic::ID IID = Fn->getIntrinsicID(); | ||||
| 6391 | |||||
| 6392 | if (IID) { | ||||
| 6393 | Check((IID == Intrinsic::objc_retainAutoreleasedReturnValue ||do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false) | ||||
| 6394 | IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue),do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false) | ||||
| 6395 | "invalid function argument", Call)do { if (!((IID == Intrinsic::objc_retainAutoreleasedReturnValue || IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue ))) { CheckFailed("invalid function argument", Call); return; } } while (false); | ||||
| 6396 | } else { | ||||
| 6397 | StringRef FnName = Fn->getName(); | ||||
| 6398 | Check((FnName == "objc_retainAutoreleasedReturnValue" ||do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ) | ||||
| 6399 | FnName == "objc_unsafeClaimAutoreleasedReturnValue"),do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ) | ||||
| 6400 | "invalid function argument", Call)do { if (!((FnName == "objc_retainAutoreleasedReturnValue" || FnName == "objc_unsafeClaimAutoreleasedReturnValue"))) { CheckFailed ("invalid function argument", Call); return; } } while (false ); | ||||
| 6401 | } | ||||
| 6402 | } | ||||
| 6403 | |||||
| 6404 | void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) { | ||||
| 6405 | bool HasSource = F.getSource().has_value(); | ||||
| 6406 | if (!HasSourceDebugInfo.count(&U)) | ||||
| 6407 | HasSourceDebugInfo[&U] = HasSource; | ||||
| 6408 | CheckDI(HasSource == HasSourceDebugInfo[&U],do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ) | ||||
| 6409 | "inconsistent use of embedded source")do { if (!(HasSource == HasSourceDebugInfo[&U])) { DebugInfoCheckFailed ("inconsistent use of embedded source"); return; } } while (false ); | ||||
| 6410 | } | ||||
| 6411 | |||||
| 6412 | void Verifier::verifyNoAliasScopeDecl() { | ||||
| 6413 | if (NoAliasScopeDecls.empty()) | ||||
| 6414 | return; | ||||
| 6415 | |||||
| 6416 | // only a single scope must be declared at a time. | ||||
| 6417 | for (auto *II : NoAliasScopeDecls) { | ||||
| 6418 | assert(II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl &&(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "llvm/lib/IR/Verifier.cpp", 6419, __extension__ __PRETTY_FUNCTION__ )) | ||||
| 6419 | "Not a llvm.experimental.noalias.scope.decl ?")(static_cast <bool> (II->getIntrinsicID() == Intrinsic ::experimental_noalias_scope_decl && "Not a llvm.experimental.noalias.scope.decl ?" ) ? void (0) : __assert_fail ("II->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl && \"Not a llvm.experimental.noalias.scope.decl ?\"" , "llvm/lib/IR/Verifier.cpp", 6419, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 6420 | const auto *ScopeListMV = dyn_cast<MetadataAsValue>( | ||||
| 6421 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
| 6422 | Check(ScopeListMV != nullptr,do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 6423 | "llvm.experimental.noalias.scope.decl must have a MetadataAsValue "do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 6424 | "argument",do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false) | ||||
| 6425 | II)do { if (!(ScopeListMV != nullptr)) { CheckFailed("llvm.experimental.noalias.scope.decl must have a MetadataAsValue " "argument", II); return; } } while (false); | ||||
| 6426 | |||||
| 6427 | const auto *ScopeListMD = dyn_cast<MDNode>(ScopeListMV->getMetadata()); | ||||
| 6428 | Check(ScopeListMD != nullptr, "!id.scope.list must point to an MDNode", II)do { if (!(ScopeListMD != nullptr)) { CheckFailed("!id.scope.list must point to an MDNode" , II); return; } } while (false); | ||||
| 6429 | Check(ScopeListMD->getNumOperands() == 1,do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false) | ||||
| 6430 | "!id.scope.list must point to a list with a single scope", II)do { if (!(ScopeListMD->getNumOperands() == 1)) { CheckFailed ("!id.scope.list must point to a list with a single scope", II ); return; } } while (false); | ||||
| 6431 | visitAliasScopeListMetadata(ScopeListMD); | ||||
| 6432 | } | ||||
| 6433 | |||||
| 6434 | // Only check the domination rule when requested. Once all passes have been | ||||
| 6435 | // adapted this option can go away. | ||||
| 6436 | if (!VerifyNoAliasScopeDomination) | ||||
| 6437 | return; | ||||
| 6438 | |||||
| 6439 | // Now sort the intrinsics based on the scope MDNode so that declarations of | ||||
| 6440 | // the same scopes are next to each other. | ||||
| 6441 | auto GetScope = [](IntrinsicInst *II) { | ||||
| 6442 | const auto *ScopeListMV = cast<MetadataAsValue>( | ||||
| 6443 | II->getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | ||||
| 6444 | return &cast<MDNode>(ScopeListMV->getMetadata())->getOperand(0); | ||||
| 6445 | }; | ||||
| 6446 | |||||
| 6447 | // We are sorting on MDNode pointers here. For valid input IR this is ok. | ||||
| 6448 | // TODO: Sort on Metadata ID to avoid non-deterministic error messages. | ||||
| 6449 | auto Compare = [GetScope](IntrinsicInst *Lhs, IntrinsicInst *Rhs) { | ||||
| 6450 | return GetScope(Lhs) < GetScope(Rhs); | ||||
| 6451 | }; | ||||
| 6452 | |||||
| 6453 | llvm::sort(NoAliasScopeDecls, Compare); | ||||
| 6454 | |||||
| 6455 | // Go over the intrinsics and check that for the same scope, they are not | ||||
| 6456 | // dominating each other. | ||||
| 6457 | auto ItCurrent = NoAliasScopeDecls.begin(); | ||||
| 6458 | while (ItCurrent != NoAliasScopeDecls.end()) { | ||||
| 6459 | auto CurScope = GetScope(*ItCurrent); | ||||
| 6460 | auto ItNext = ItCurrent; | ||||
| 6461 | do { | ||||
| 6462 | ++ItNext; | ||||
| 6463 | } while (ItNext != NoAliasScopeDecls.end() && | ||||
| 6464 | GetScope(*ItNext) == CurScope); | ||||
| 6465 | |||||
| 6466 | // [ItCurrent, ItNext) represents the declarations for the same scope. | ||||
| 6467 | // Ensure they are not dominating each other.. but only if it is not too | ||||
| 6468 | // expensive. | ||||
| 6469 | if (ItNext - ItCurrent < 32) | ||||
| 6470 | for (auto *I : llvm::make_range(ItCurrent, ItNext)) | ||||
| 6471 | for (auto *J : llvm::make_range(ItCurrent, ItNext)) | ||||
| 6472 | if (I != J) | ||||
| 6473 | Check(!DT.dominates(I, J),do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 6474 | "llvm.experimental.noalias.scope.decl dominates another one "do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 6475 | "with the same scope",do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false) | ||||
| 6476 | I)do { if (!(!DT.dominates(I, J))) { CheckFailed("llvm.experimental.noalias.scope.decl dominates another one " "with the same scope", I); return; } } while (false); | ||||
| 6477 | ItCurrent = ItNext; | ||||
| 6478 | } | ||||
| 6479 | } | ||||
| 6480 | |||||
| 6481 | //===----------------------------------------------------------------------===// | ||||
| 6482 | // Implement the public interfaces to this file... | ||||
| 6483 | //===----------------------------------------------------------------------===// | ||||
| 6484 | |||||
| 6485 | bool llvm::verifyFunction(const Function &f, raw_ostream *OS) { | ||||
| 6486 | Function &F = const_cast<Function &>(f); | ||||
| 6487 | |||||
| 6488 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
| 6489 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true, *f.getParent()); | ||||
| 6490 | |||||
| 6491 | // Note that this function's return value is inverted from what you would | ||||
| 6492 | // expect of a function called "verify". | ||||
| 6493 | return !V.verify(F); | ||||
| 6494 | } | ||||
| 6495 | |||||
| 6496 | bool llvm::verifyModule(const Module &M, raw_ostream *OS, | ||||
| 6497 | bool *BrokenDebugInfo) { | ||||
| 6498 | // Don't use a raw_null_ostream. Printing IR is expensive. | ||||
| 6499 | Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo, M); | ||||
| 6500 | |||||
| 6501 | bool Broken = false; | ||||
| 6502 | for (const Function &F : M) | ||||
| 6503 | Broken |= !V.verify(F); | ||||
| 6504 | |||||
| 6505 | Broken |= !V.verify(); | ||||
| 6506 | if (BrokenDebugInfo) | ||||
| 6507 | *BrokenDebugInfo = V.hasBrokenDebugInfo(); | ||||
| 6508 | // Note that this function's return value is inverted from what you would | ||||
| 6509 | // expect of a function called "verify". | ||||
| 6510 | return Broken; | ||||
| 6511 | } | ||||
| 6512 | |||||
| 6513 | namespace { | ||||
| 6514 | |||||
| 6515 | struct VerifierLegacyPass : public FunctionPass { | ||||
| 6516 | static char ID; | ||||
| 6517 | |||||
| 6518 | std::unique_ptr<Verifier> V; | ||||
| 6519 | bool FatalErrors = true; | ||||
| 6520 | |||||
| 6521 | VerifierLegacyPass() : FunctionPass(ID) { | ||||
| 6522 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
| 6523 | } | ||||
| 6524 | explicit VerifierLegacyPass(bool FatalErrors) | ||||
| 6525 | : FunctionPass(ID), | ||||
| 6526 | FatalErrors(FatalErrors) { | ||||
| 6527 | initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry()); | ||||
| 6528 | } | ||||
| 6529 | |||||
| 6530 | bool doInitialization(Module &M) override { | ||||
| 6531 | V = std::make_unique<Verifier>( | ||||
| 6532 | &dbgs(), /*ShouldTreatBrokenDebugInfoAsError=*/false, M); | ||||
| 6533 | return false; | ||||
| 6534 | } | ||||
| 6535 | |||||
| 6536 | bool runOnFunction(Function &F) override { | ||||
| 6537 | if (!V->verify(F) && FatalErrors) { | ||||
| 6538 | errs() << "in function " << F.getName() << '\n'; | ||||
| 6539 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
| 6540 | } | ||||
| 6541 | return false; | ||||
| 6542 | } | ||||
| 6543 | |||||
| 6544 | bool doFinalization(Module &M) override { | ||||
| 6545 | bool HasErrors = false; | ||||
| 6546 | for (Function &F : M) | ||||
| 6547 | if (F.isDeclaration()) | ||||
| 6548 | HasErrors |= !V->verify(F); | ||||
| 6549 | |||||
| 6550 | HasErrors |= !V->verify(); | ||||
| 6551 | if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) | ||||
| 6552 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
| 6553 | return false; | ||||
| 6554 | } | ||||
| 6555 | |||||
| 6556 | void getAnalysisUsage(AnalysisUsage &AU) const override { | ||||
| 6557 | AU.setPreservesAll(); | ||||
| 6558 | } | ||||
| 6559 | }; | ||||
| 6560 | |||||
| 6561 | } // end anonymous namespace | ||||
| 6562 | |||||
| 6563 | /// Helper to issue failure from the TBAA verification | ||||
| 6564 | template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) { | ||||
| 6565 | if (Diagnostic) | ||||
| 6566 | return Diagnostic->CheckFailed(Args...); | ||||
| 6567 | } | ||||
| 6568 | |||||
| 6569 | #define CheckTBAA(C, ...)do { if (!(C)) { CheckFailed(...); return false; } } while (false ) \ | ||||
| 6570 | do { \ | ||||
| 6571 | if (!(C)) { \ | ||||
| 6572 | CheckFailed(__VA_ARGS__); \ | ||||
| 6573 | return false; \ | ||||
| 6574 | } \ | ||||
| 6575 | } while (false) | ||||
| 6576 | |||||
| 6577 | /// Verify that \p BaseNode can be used as the "base type" in the struct-path | ||||
| 6578 | /// TBAA scheme. This means \p BaseNode is either a scalar node, or a | ||||
| 6579 | /// struct-type node describing an aggregate data structure (like a struct). | ||||
| 6580 | TBAAVerifier::TBAABaseNodeSummary | ||||
| 6581 | TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, | ||||
| 6582 | bool IsNewFormat) { | ||||
| 6583 | if (BaseNode->getNumOperands() < 2) { | ||||
| 6584 | CheckFailed("Base nodes must have at least two operands", &I, BaseNode); | ||||
| 6585 | return {true, ~0u}; | ||||
| 6586 | } | ||||
| 6587 | |||||
| 6588 | auto Itr = TBAABaseNodes.find(BaseNode); | ||||
| 6589 | if (Itr != TBAABaseNodes.end()) | ||||
| 6590 | return Itr->second; | ||||
| 6591 | |||||
| 6592 | auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat); | ||||
| 6593 | auto InsertResult = TBAABaseNodes.insert({BaseNode, Result}); | ||||
| 6594 | (void)InsertResult; | ||||
| 6595 | assert(InsertResult.second && "We just checked!")(static_cast <bool> (InsertResult.second && "We just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"We just checked!\"" , "llvm/lib/IR/Verifier.cpp", 6595, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 6596 | return Result; | ||||
| 6597 | } | ||||
| 6598 | |||||
| 6599 | TBAAVerifier::TBAABaseNodeSummary | ||||
| 6600 | TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, | ||||
| 6601 | bool IsNewFormat) { | ||||
| 6602 | const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u}; | ||||
| 6603 | |||||
| 6604 | if (BaseNode->getNumOperands() == 2) { | ||||
| 6605 | // Scalar nodes can only be accessed at offset 0. | ||||
| 6606 | return isValidScalarTBAANode(BaseNode) | ||||
| 6607 | ? TBAAVerifier::TBAABaseNodeSummary({false, 0}) | ||||
| 6608 | : InvalidNode; | ||||
| 6609 | } | ||||
| 6610 | |||||
| 6611 | if (IsNewFormat) { | ||||
| 6612 | if (BaseNode->getNumOperands() % 3 != 0) { | ||||
| 6613 | CheckFailed("Access tag nodes must have the number of operands that is a " | ||||
| 6614 | "multiple of 3!", BaseNode); | ||||
| 6615 | return InvalidNode; | ||||
| 6616 | } | ||||
| 6617 | } else { | ||||
| 6618 | if (BaseNode->getNumOperands() % 2 != 1) { | ||||
| 6619 | CheckFailed("Struct tag nodes must have an odd number of operands!", | ||||
| 6620 | BaseNode); | ||||
| 6621 | return InvalidNode; | ||||
| 6622 | } | ||||
| 6623 | } | ||||
| 6624 | |||||
| 6625 | // Check the type size field. | ||||
| 6626 | if (IsNewFormat) { | ||||
| 6627 | auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6628 | BaseNode->getOperand(1)); | ||||
| 6629 | if (!TypeSizeNode) { | ||||
| 6630 | CheckFailed("Type size nodes must be constants!", &I, BaseNode); | ||||
| 6631 | return InvalidNode; | ||||
| 6632 | } | ||||
| 6633 | } | ||||
| 6634 | |||||
| 6635 | // Check the type name field. In the new format it can be anything. | ||||
| 6636 | if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) { | ||||
| 6637 | CheckFailed("Struct tag nodes have a string as their first operand", | ||||
| 6638 | BaseNode); | ||||
| 6639 | return InvalidNode; | ||||
| 6640 | } | ||||
| 6641 | |||||
| 6642 | bool Failed = false; | ||||
| 6643 | |||||
| 6644 | std::optional<APInt> PrevOffset; | ||||
| 6645 | unsigned BitWidth = ~0u; | ||||
| 6646 | |||||
| 6647 | // We've already checked that BaseNode is not a degenerate root node with one | ||||
| 6648 | // operand in \c verifyTBAABaseNode, so this loop should run at least once. | ||||
| 6649 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
| 6650 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
| 6651 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
| 6652 | Idx += NumOpsPerField) { | ||||
| 6653 | const MDOperand &FieldTy = BaseNode->getOperand(Idx); | ||||
| 6654 | const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1); | ||||
| 6655 | if (!isa<MDNode>(FieldTy)) { | ||||
| 6656 | CheckFailed("Incorrect field entry in struct type node!", &I, BaseNode); | ||||
| 6657 | Failed = true; | ||||
| 6658 | continue; | ||||
| 6659 | } | ||||
| 6660 | |||||
| 6661 | auto *OffsetEntryCI = | ||||
| 6662 | mdconst::dyn_extract_or_null<ConstantInt>(FieldOffset); | ||||
| 6663 | if (!OffsetEntryCI) { | ||||
| 6664 | CheckFailed("Offset entries must be constants!", &I, BaseNode); | ||||
| 6665 | Failed = true; | ||||
| 6666 | continue; | ||||
| 6667 | } | ||||
| 6668 | |||||
| 6669 | if (BitWidth == ~0u) | ||||
| 6670 | BitWidth = OffsetEntryCI->getBitWidth(); | ||||
| 6671 | |||||
| 6672 | if (OffsetEntryCI->getBitWidth() != BitWidth) { | ||||
| 6673 | CheckFailed( | ||||
| 6674 | "Bitwidth between the offsets and struct type entries must match", &I, | ||||
| 6675 | BaseNode); | ||||
| 6676 | Failed = true; | ||||
| 6677 | continue; | ||||
| 6678 | } | ||||
| 6679 | |||||
| 6680 | // NB! As far as I can tell, we generate a non-strictly increasing offset | ||||
| 6681 | // sequence only from structs that have zero size bit fields. When | ||||
| 6682 | // recursing into a contained struct in \c getFieldNodeFromTBAABaseNode we | ||||
| 6683 | // pick the field lexically the latest in struct type metadata node. This | ||||
| 6684 | // mirrors the actual behavior of the alias analysis implementation. | ||||
| 6685 | bool IsAscending = | ||||
| 6686 | !PrevOffset || PrevOffset->ule(OffsetEntryCI->getValue()); | ||||
| 6687 | |||||
| 6688 | if (!IsAscending) { | ||||
| 6689 | CheckFailed("Offsets must be increasing!", &I, BaseNode); | ||||
| 6690 | Failed = true; | ||||
| 6691 | } | ||||
| 6692 | |||||
| 6693 | PrevOffset = OffsetEntryCI->getValue(); | ||||
| 6694 | |||||
| 6695 | if (IsNewFormat) { | ||||
| 6696 | auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6697 | BaseNode->getOperand(Idx + 2)); | ||||
| 6698 | if (!MemberSizeNode) { | ||||
| 6699 | CheckFailed("Member size entries must be constants!", &I, BaseNode); | ||||
| 6700 | Failed = true; | ||||
| 6701 | continue; | ||||
| 6702 | } | ||||
| 6703 | } | ||||
| 6704 | } | ||||
| 6705 | |||||
| 6706 | return Failed ? InvalidNode | ||||
| 6707 | : TBAAVerifier::TBAABaseNodeSummary(false, BitWidth); | ||||
| 6708 | } | ||||
| 6709 | |||||
| 6710 | static bool IsRootTBAANode(const MDNode *MD) { | ||||
| 6711 | return MD->getNumOperands() < 2; | ||||
| 6712 | } | ||||
| 6713 | |||||
| 6714 | static bool IsScalarTBAANodeImpl(const MDNode *MD, | ||||
| 6715 | SmallPtrSetImpl<const MDNode *> &Visited) { | ||||
| 6716 | if (MD->getNumOperands() != 2 && MD->getNumOperands() != 3) | ||||
| 6717 | return false; | ||||
| 6718 | |||||
| 6719 | if (!isa<MDString>(MD->getOperand(0))) | ||||
| 6720 | return false; | ||||
| 6721 | |||||
| 6722 | if (MD->getNumOperands() == 3) { | ||||
| 6723 | auto *Offset = mdconst::dyn_extract<ConstantInt>(MD->getOperand(2)); | ||||
| 6724 | if (!(Offset && Offset->isZero() && isa<MDString>(MD->getOperand(0)))) | ||||
| 6725 | return false; | ||||
| 6726 | } | ||||
| 6727 | |||||
| 6728 | auto *Parent = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
| 6729 | return Parent && Visited.insert(Parent).second && | ||||
| 6730 | (IsRootTBAANode(Parent) || IsScalarTBAANodeImpl(Parent, Visited)); | ||||
| 6731 | } | ||||
| 6732 | |||||
| 6733 | bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) { | ||||
| 6734 | auto ResultIt = TBAAScalarNodes.find(MD); | ||||
| 6735 | if (ResultIt != TBAAScalarNodes.end()) | ||||
| 6736 | return ResultIt->second; | ||||
| 6737 | |||||
| 6738 | SmallPtrSet<const MDNode *, 4> Visited; | ||||
| 6739 | bool Result = IsScalarTBAANodeImpl(MD, Visited); | ||||
| 6740 | auto InsertResult = TBAAScalarNodes.insert({MD, Result}); | ||||
| 6741 | (void)InsertResult; | ||||
| 6742 | assert(InsertResult.second && "Just checked!")(static_cast <bool> (InsertResult.second && "Just checked!" ) ? void (0) : __assert_fail ("InsertResult.second && \"Just checked!\"" , "llvm/lib/IR/Verifier.cpp", 6742, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 6743 | |||||
| 6744 | return Result; | ||||
| 6745 | } | ||||
| 6746 | |||||
| 6747 | /// Returns the field node at the offset \p Offset in \p BaseNode. Update \p | ||||
| 6748 | /// Offset in place to be the offset within the field node returned. | ||||
| 6749 | /// | ||||
| 6750 | /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode. | ||||
| 6751 | MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I, | ||||
| 6752 | const MDNode *BaseNode, | ||||
| 6753 | APInt &Offset, | ||||
| 6754 | bool IsNewFormat) { | ||||
| 6755 | assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!")(static_cast <bool> (BaseNode->getNumOperands() >= 2 && "Invalid base node!") ? void (0) : __assert_fail ("BaseNode->getNumOperands() >= 2 && \"Invalid base node!\"" , "llvm/lib/IR/Verifier.cpp", 6755, __extension__ __PRETTY_FUNCTION__ )); | ||||
| 6756 | |||||
| 6757 | // Scalar nodes have only one possible "field" -- their parent in the access | ||||
| 6758 | // hierarchy. Offset must be zero at this point, but our caller is supposed | ||||
| 6759 | // to check that. | ||||
| 6760 | if (BaseNode->getNumOperands() == 2) | ||||
| 6761 | return cast<MDNode>(BaseNode->getOperand(1)); | ||||
| 6762 | |||||
| 6763 | unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; | ||||
| 6764 | unsigned NumOpsPerField = IsNewFormat ? 3 : 2; | ||||
| 6765 | for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); | ||||
| 6766 | Idx += NumOpsPerField) { | ||||
| 6767 | auto *OffsetEntryCI = | ||||
| 6768 | mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1)); | ||||
| 6769 | if (OffsetEntryCI->getValue().ugt(Offset)) { | ||||
| 6770 | if (Idx == FirstFieldOpNo) { | ||||
| 6771 | CheckFailed("Could not find TBAA parent in struct type node", &I, | ||||
| 6772 | BaseNode, &Offset); | ||||
| 6773 | return nullptr; | ||||
| 6774 | } | ||||
| 6775 | |||||
| 6776 | unsigned PrevIdx = Idx - NumOpsPerField; | ||||
| 6777 | auto *PrevOffsetEntryCI = | ||||
| 6778 | mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1)); | ||||
| 6779 | Offset -= PrevOffsetEntryCI->getValue(); | ||||
| 6780 | return cast<MDNode>(BaseNode->getOperand(PrevIdx)); | ||||
| 6781 | } | ||||
| 6782 | } | ||||
| 6783 | |||||
| 6784 | unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField; | ||||
| 6785 | auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( | ||||
| 6786 | BaseNode->getOperand(LastIdx + 1)); | ||||
| 6787 | Offset -= LastOffsetEntryCI->getValue(); | ||||
| 6788 | return cast<MDNode>(BaseNode->getOperand(LastIdx)); | ||||
| 6789 | } | ||||
| 6790 | |||||
| 6791 | static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { | ||||
| 6792 | if (!Type || Type->getNumOperands() < 3) | ||||
| 6793 | return false; | ||||
| 6794 | |||||
| 6795 | // In the new format type nodes shall have a reference to the parent type as | ||||
| 6796 | // its first operand. | ||||
| 6797 | return isa_and_nonnull<MDNode>(Type->getOperand(0)); | ||||
| 6798 | } | ||||
| 6799 | |||||
| 6800 | bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) { | ||||
| 6801 | CheckTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6802 | isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6803 | isa<AtomicCmpXchgInst>(I),do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false) | ||||
| 6804 | "This instruction shall not have a TBAA access tag!", &I)do { if (!(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) || isa<VAArgInst>(I) || isa< AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I))) { CheckFailed ("This instruction shall not have a TBAA access tag!", &I ); return false; } } while (false); | ||||
| 6805 | |||||
| 6806 | bool IsStructPathTBAA = | ||||
| 6807 | isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; | ||||
| 6808 | |||||
| 6809 | CheckTBAA(IsStructPathTBAA,do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
| 6810 | "Old-style TBAA is no longer allowed, use struct-path TBAA instead",do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false) | ||||
| 6811 | &I)do { if (!(IsStructPathTBAA)) { CheckFailed("Old-style TBAA is no longer allowed, use struct-path TBAA instead" , &I); return false; } } while (false); | ||||
| 6812 | |||||
| 6813 | MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0)); | ||||
| 6814 | MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); | ||||
| 6815 | |||||
| 6816 | bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); | ||||
| 6817 | |||||
| 6818 | if (IsNewFormat) { | ||||
| 6819 | CheckTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false) | ||||
| 6820 | "Access tag metadata must have either 4 or 5 operands", &I, MD)do { if (!(MD->getNumOperands() == 4 || MD->getNumOperands () == 5)) { CheckFailed("Access tag metadata must have either 4 or 5 operands" , &I, MD); return false; } } while (false); | ||||
| 6821 | } else { | ||||
| 6822 | CheckTBAA(MD->getNumOperands() < 5,do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false) | ||||
| 6823 | "Struct tag metadata must have either 3 or 4 operands", &I, MD)do { if (!(MD->getNumOperands() < 5)) { CheckFailed("Struct tag metadata must have either 3 or 4 operands" , &I, MD); return false; } } while (false); | ||||
| 6824 | } | ||||
| 6825 | |||||
| 6826 | // Check the access size field. | ||||
| 6827 | if (IsNewFormat) { | ||||
| 6828 | auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6829 | MD->getOperand(3)); | ||||
| 6830 | CheckTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD)do { if (!(AccessSizeNode)) { CheckFailed("Access size field must be a constant" , &I, MD); return false; } } while (false); | ||||
| 6831 | } | ||||
| 6832 | |||||
| 6833 | // Check the immutability flag. | ||||
| 6834 | unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; | ||||
| 6835 | if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { | ||||
| 6836 | auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( | ||||
| 6837 | MD->getOperand(ImmutabilityFlagOpNo)); | ||||
| 6838 | CheckTBAA(IsImmutableCI,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
| 6839 | "Immutability tag on struct tag metadata must be a constant", &I,do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false) | ||||
| 6840 | MD)do { if (!(IsImmutableCI)) { CheckFailed("Immutability tag on struct tag metadata must be a constant" , &I, MD); return false; } } while (false); | ||||
| 6841 | CheckTBAA(do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6842 | IsImmutableCI->isZero() || IsImmutableCI->isOne(),do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6843 | "Immutability part of the struct tag metadata must be either 0 or 1",do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false) | ||||
| 6844 | &I, MD)do { if (!(IsImmutableCI->isZero() || IsImmutableCI->isOne ())) { CheckFailed("Immutability part of the struct tag metadata must be either 0 or 1" , &I, MD); return false; } } while (false); | ||||
| 6845 | } | ||||
| 6846 | |||||
| 6847 | CheckTBAA(BaseNode && AccessType,do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6848 | "Malformed struct tag metadata: base and access-type "do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6849 | "should be non-null and point to Metadata nodes",do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false) | ||||
| 6850 | &I, MD, BaseNode, AccessType)do { if (!(BaseNode && AccessType)) { CheckFailed("Malformed struct tag metadata: base and access-type " "should be non-null and point to Metadata nodes", &I, MD , BaseNode, AccessType); return false; } } while (false); | ||||
| 6851 | |||||
| 6852 | if (!IsNewFormat) { | ||||
| 6853 | CheckTBAA(isValidScalarTBAANode(AccessType),do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
| 6854 | "Access type node must be a valid scalar type", &I, MD,do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false) | ||||
| 6855 | AccessType)do { if (!(isValidScalarTBAANode(AccessType))) { CheckFailed( "Access type node must be a valid scalar type", &I, MD, AccessType ); return false; } } while (false); | ||||
| 6856 | } | ||||
| 6857 | |||||
| 6858 | auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2)); | ||||
| 6859 | CheckTBAA(OffsetCI, "Offset must be constant integer", &I, MD)do { if (!(OffsetCI)) { CheckFailed("Offset must be constant integer" , &I, MD); return false; } } while (false); | ||||
| 6860 | |||||
| 6861 | APInt Offset = OffsetCI->getValue(); | ||||
| 6862 | bool SeenAccessTypeInPath = false; | ||||
| 6863 | |||||
| 6864 | SmallPtrSet<MDNode *, 4> StructPath; | ||||
| 6865 | |||||
| 6866 | for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); | ||||
| 6867 | BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, | ||||
| 6868 | IsNewFormat)) { | ||||
| 6869 | if (!StructPath.insert(BaseNode).second) { | ||||
| 6870 | CheckFailed("Cycle detected in struct path", &I, MD); | ||||
| 6871 | return false; | ||||
| 6872 | } | ||||
| 6873 | |||||
| 6874 | bool Invalid; | ||||
| 6875 | unsigned BaseNodeBitWidth; | ||||
| 6876 | std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, | ||||
| 6877 | IsNewFormat); | ||||
| 6878 | |||||
| 6879 | // If the base node is invalid in itself, then we've already printed all the | ||||
| 6880 | // errors we wanted to print. | ||||
| 6881 | if (Invalid) | ||||
| 6882 | return false; | ||||
| 6883 | |||||
| 6884 | SeenAccessTypeInPath |= BaseNode == AccessType; | ||||
| 6885 | |||||
| 6886 | if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType) | ||||
| 6887 | CheckTBAA(Offset == 0, "Offset not zero at the point of scalar access",do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false) | ||||
| 6888 | &I, MD, &Offset)do { if (!(Offset == 0)) { CheckFailed("Offset not zero at the point of scalar access" , &I, MD, &Offset); return false; } } while (false); | ||||
| 6889 | |||||
| 6890 | CheckTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6891 | (BaseNodeBitWidth == 0 && Offset == 0) ||do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6892 | (IsNewFormat && BaseNodeBitWidth == ~0u),do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6893 | "Access bit-width not the same as description bit-width", &I, MD,do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false) | ||||
| 6894 | BaseNodeBitWidth, Offset.getBitWidth())do { if (!(BaseNodeBitWidth == Offset.getBitWidth() || (BaseNodeBitWidth == 0 && Offset == 0) || (IsNewFormat && BaseNodeBitWidth == ~0u))) { CheckFailed("Access bit-width not the same as description bit-width" , &I, MD, BaseNodeBitWidth, Offset.getBitWidth()); return false; } } while (false); | ||||
| 6895 | |||||
| 6896 | if (IsNewFormat && SeenAccessTypeInPath) | ||||
| 6897 | break; | ||||
| 6898 | } | ||||
| 6899 | |||||
| 6900 | CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", &I,do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false) | ||||
| 6901 | MD)do { if (!(SeenAccessTypeInPath)) { CheckFailed("Did not see access type in access path!" , &I, MD); return false; } } while (false); | ||||
| 6902 | return true; | ||||
| 6903 | } | ||||
| 6904 | |||||
| 6905 | char VerifierLegacyPass::ID = 0; | ||||
| 6906 | INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)static void *initializeVerifierLegacyPassPassOnce(PassRegistry &Registry) { PassInfo *PI = new PassInfo( "Module Verifier" , "verify", &VerifierLegacyPass::ID, PassInfo::NormalCtor_t (callDefaultCtor<VerifierLegacyPass>), false, false); Registry .registerPass(*PI, true); return PI; } static llvm::once_flag InitializeVerifierLegacyPassPassFlag; void llvm::initializeVerifierLegacyPassPass (PassRegistry &Registry) { llvm::call_once(InitializeVerifierLegacyPassPassFlag , initializeVerifierLegacyPassPassOnce, std::ref(Registry)); } | ||||
| 6907 | |||||
| 6908 | FunctionPass *llvm::createVerifierPass(bool FatalErrors) { | ||||
| 6909 | return new VerifierLegacyPass(FatalErrors); | ||||
| 6910 | } | ||||
| 6911 | |||||
| 6912 | AnalysisKey VerifierAnalysis::Key; | ||||
| 6913 | VerifierAnalysis::Result VerifierAnalysis::run(Module &M, | ||||
| 6914 | ModuleAnalysisManager &) { | ||||
| 6915 | Result Res; | ||||
| 6916 | Res.IRBroken = llvm::verifyModule(M, &dbgs(), &Res.DebugInfoBroken); | ||||
| 6917 | return Res; | ||||
| 6918 | } | ||||
| 6919 | |||||
| 6920 | VerifierAnalysis::Result VerifierAnalysis::run(Function &F, | ||||
| 6921 | FunctionAnalysisManager &) { | ||||
| 6922 | return { llvm::verifyFunction(F, &dbgs()), false }; | ||||
| 6923 | } | ||||
| 6924 | |||||
| 6925 | PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) { | ||||
| 6926 | auto Res = AM.getResult<VerifierAnalysis>(M); | ||||
| 6927 | if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) | ||||
| 6928 | report_fatal_error("Broken module found, compilation aborted!"); | ||||
| 6929 | |||||
| 6930 | return PreservedAnalyses::all(); | ||||
| 6931 | } | ||||
| 6932 | |||||
| 6933 | PreservedAnalyses VerifierPass::run(Function &F, FunctionAnalysisManager &AM) { | ||||
| 6934 | auto res = AM.getResult<VerifierAnalysis>(F); | ||||
| 6935 | if (res.IRBroken && FatalErrors) | ||||
| 6936 | report_fatal_error("Broken function found, compilation aborted!"); | ||||
| 6937 | |||||
| 6938 | return PreservedAnalyses::all(); | ||||
| 6939 | } |
| 1 | //===- llvm/IR/DebugInfoMetadata.h - Debug info metadata --------*- C++ -*-===// | ||||||||||||
| 2 | // | ||||||||||||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||||||||||||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||||||||||||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||||||||||||
| 6 | // | ||||||||||||
| 7 | //===----------------------------------------------------------------------===// | ||||||||||||
| 8 | // | ||||||||||||
| 9 | // Declarations for metadata specific to debug info. | ||||||||||||
| 10 | // | ||||||||||||
| 11 | //===----------------------------------------------------------------------===// | ||||||||||||
| 12 | |||||||||||||
| 13 | #ifndef LLVM_IR_DEBUGINFOMETADATA_H | ||||||||||||
| 14 | #define LLVM_IR_DEBUGINFOMETADATA_H | ||||||||||||
| 15 | |||||||||||||
| 16 | #include "llvm/ADT/ArrayRef.h" | ||||||||||||
| 17 | #include "llvm/ADT/BitmaskEnum.h" | ||||||||||||
| 18 | #include "llvm/ADT/PointerUnion.h" | ||||||||||||
| 19 | #include "llvm/ADT/STLExtras.h" | ||||||||||||
| 20 | #include "llvm/ADT/SmallVector.h" | ||||||||||||
| 21 | #include "llvm/ADT/StringRef.h" | ||||||||||||
| 22 | #include "llvm/ADT/iterator_range.h" | ||||||||||||
| 23 | #include "llvm/IR/Constants.h" | ||||||||||||
| 24 | #include "llvm/IR/Metadata.h" | ||||||||||||
| 25 | #include "llvm/Support/Casting.h" | ||||||||||||
| 26 | #include "llvm/Support/CommandLine.h" | ||||||||||||
| 27 | #include "llvm/Support/Discriminator.h" | ||||||||||||
| 28 | #include <cassert> | ||||||||||||
| 29 | #include <climits> | ||||||||||||
| 30 | #include <cstddef> | ||||||||||||
| 31 | #include <cstdint> | ||||||||||||
| 32 | #include <iterator> | ||||||||||||
| 33 | #include <optional> | ||||||||||||
| 34 | #include <vector> | ||||||||||||
| 35 | |||||||||||||
| 36 | // Helper macros for defining get() overrides. | ||||||||||||
| 37 | #define DEFINE_MDNODE_GET_UNPACK_IMPL(...) __VA_ARGS__ | ||||||||||||
| 38 | #define DEFINE_MDNODE_GET_UNPACK(ARGS) DEFINE_MDNODE_GET_UNPACK_IMPL ARGS | ||||||||||||
| 39 | #define DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } \ | ||||||||||||
| 40 | static CLASS *getDistinct(LLVMContext &Context, \ | ||||||||||||
| 41 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
| 42 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Distinct); \ | ||||||||||||
| 43 | } \ | ||||||||||||
| 44 | static Temp##CLASS getTemporary(LLVMContext &Context, \ | ||||||||||||
| 45 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
| 46 | return Temp##CLASS( \ | ||||||||||||
| 47 | getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary)); \ | ||||||||||||
| 48 | } | ||||||||||||
| 49 | #define DEFINE_MDNODE_GET(CLASS, FORMAL, ARGS) \ | ||||||||||||
| 50 | static CLASS *get(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
| 51 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued); \ | ||||||||||||
| 52 | } \ | ||||||||||||
| 53 | static CLASS *getIfExists(LLVMContext &Context, \ | ||||||||||||
| 54 | DEFINE_MDNODE_GET_UNPACK(FORMAL)) { \ | ||||||||||||
| 55 | return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Uniqued, \ | ||||||||||||
| 56 | /* ShouldCreate */ false); \ | ||||||||||||
| 57 | } \ | ||||||||||||
| 58 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(CLASS, FORMAL, ARGS)static CLASS *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK (FORMAL)) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK( ARGS), Distinct); } static TempCLASS getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK(FORMAL)) { return TempCLASS ( getImpl(Context, DEFINE_MDNODE_GET_UNPACK(ARGS), Temporary) ); } | ||||||||||||
| 59 | |||||||||||||
| 60 | namespace llvm { | ||||||||||||
| 61 | |||||||||||||
| 62 | namespace dwarf { | ||||||||||||
| 63 | enum Tag : uint16_t; | ||||||||||||
| 64 | } | ||||||||||||
| 65 | |||||||||||||
| 66 | class DbgVariableIntrinsic; | ||||||||||||
| 67 | |||||||||||||
| 68 | extern cl::opt<bool> EnableFSDiscriminator; | ||||||||||||
| 69 | |||||||||||||
| 70 | class DITypeRefArray { | ||||||||||||
| 71 | const MDTuple *N = nullptr; | ||||||||||||
| 72 | |||||||||||||
| 73 | public: | ||||||||||||
| 74 | DITypeRefArray() = default; | ||||||||||||
| 75 | DITypeRefArray(const MDTuple *N) : N(N) {} | ||||||||||||
| 76 | |||||||||||||
| 77 | explicit operator bool() const { return get(); } | ||||||||||||
| 78 | explicit operator MDTuple *() const { return get(); } | ||||||||||||
| 79 | |||||||||||||
| 80 | MDTuple *get() const { return const_cast<MDTuple *>(N); } | ||||||||||||
| 81 | MDTuple *operator->() const { return get(); } | ||||||||||||
| 82 | MDTuple &operator*() const { return *get(); } | ||||||||||||
| 83 | |||||||||||||
| 84 | // FIXME: Fix callers and remove condition on N. | ||||||||||||
| 85 | unsigned size() const { return N ? N->getNumOperands() : 0u; } | ||||||||||||
| 86 | DIType *operator[](unsigned I) const { | ||||||||||||
| 87 | return cast_or_null<DIType>(N->getOperand(I)); | ||||||||||||
| 88 | } | ||||||||||||
| 89 | |||||||||||||
| 90 | class iterator { | ||||||||||||
| 91 | MDNode::op_iterator I = nullptr; | ||||||||||||
| 92 | |||||||||||||
| 93 | public: | ||||||||||||
| 94 | using iterator_category = std::input_iterator_tag; | ||||||||||||
| 95 | using value_type = DIType *; | ||||||||||||
| 96 | using difference_type = std::ptrdiff_t; | ||||||||||||
| 97 | using pointer = void; | ||||||||||||
| 98 | using reference = DIType *; | ||||||||||||
| 99 | |||||||||||||
| 100 | iterator() = default; | ||||||||||||
| 101 | explicit iterator(MDNode::op_iterator I) : I(I) {} | ||||||||||||
| 102 | |||||||||||||
| 103 | DIType *operator*() const { return cast_or_null<DIType>(*I); } | ||||||||||||
| 104 | |||||||||||||
| 105 | iterator &operator++() { | ||||||||||||
| 106 | ++I; | ||||||||||||
| 107 | return *this; | ||||||||||||
| 108 | } | ||||||||||||
| 109 | |||||||||||||
| 110 | iterator operator++(int) { | ||||||||||||
| 111 | iterator Temp(*this); | ||||||||||||
| 112 | ++I; | ||||||||||||
| 113 | return Temp; | ||||||||||||
| 114 | } | ||||||||||||
| 115 | |||||||||||||
| 116 | bool operator==(const iterator &X) const { return I == X.I; } | ||||||||||||
| 117 | bool operator!=(const iterator &X) const { return I != X.I; } | ||||||||||||
| 118 | }; | ||||||||||||
| 119 | |||||||||||||
| 120 | // FIXME: Fix callers and remove condition on N. | ||||||||||||
| 121 | iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } | ||||||||||||
| 122 | iterator end() const { return N ? iterator(N->op_end()) : iterator(); } | ||||||||||||
| 123 | }; | ||||||||||||
| 124 | |||||||||||||
| 125 | /// Tagged DWARF-like metadata node. | ||||||||||||
| 126 | /// | ||||||||||||
| 127 | /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, | ||||||||||||
| 128 | /// defined in llvm/BinaryFormat/Dwarf.h). Called \a DINode because it's | ||||||||||||
| 129 | /// potentially used for non-DWARF output. | ||||||||||||
| 130 | class DINode : public MDNode { | ||||||||||||
| 131 | friend class LLVMContextImpl; | ||||||||||||
| 132 | friend class MDNode; | ||||||||||||
| 133 | |||||||||||||
| 134 | protected: | ||||||||||||
| 135 | DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
| 136 | ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = std::nullopt) | ||||||||||||
| 137 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||||||||||
| 138 | assert(Tag < 1u << 16)(static_cast <bool> (Tag < 1u << 16) ? void (0 ) : __assert_fail ("Tag < 1u << 16", "llvm/include/llvm/IR/DebugInfoMetadata.h" , 138, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 139 | SubclassData16 = Tag; | ||||||||||||
| 140 | } | ||||||||||||
| 141 | ~DINode() = default; | ||||||||||||
| 142 | |||||||||||||
| 143 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||||||||||
| 144 | return cast_or_null<Ty>(getOperand(I)); | ||||||||||||
| 145 | } | ||||||||||||
| 146 | |||||||||||||
| 147 | StringRef getStringOperand(unsigned I) const { | ||||||||||||
| 148 | if (auto *S = getOperandAs<MDString>(I)) | ||||||||||||
| 149 | return S->getString(); | ||||||||||||
| 150 | return StringRef(); | ||||||||||||
| 151 | } | ||||||||||||
| 152 | |||||||||||||
| 153 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||||||||||
| 154 | if (S.empty()) | ||||||||||||
| 155 | return nullptr; | ||||||||||||
| 156 | return MDString::get(Context, S); | ||||||||||||
| 157 | } | ||||||||||||
| 158 | |||||||||||||
| 159 | /// Allow subclasses to mutate the tag. | ||||||||||||
| 160 | void setTag(unsigned Tag) { SubclassData16 = Tag; } | ||||||||||||
| 161 | |||||||||||||
| 162 | public: | ||||||||||||
| 163 | dwarf::Tag getTag() const; | ||||||||||||
| 164 | |||||||||||||
| 165 | /// Debug info flags. | ||||||||||||
| 166 | /// | ||||||||||||
| 167 | /// The three accessibility flags are mutually exclusive and rolled together | ||||||||||||
| 168 | /// in the first two bits. | ||||||||||||
| 169 | enum DIFlags : uint32_t { | ||||||||||||
| 170 | #define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, | ||||||||||||
| 171 | #define DI_FLAG_LARGEST_NEEDED | ||||||||||||
| 172 | #include "llvm/IR/DebugInfoFlags.def" | ||||||||||||
| 173 | FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic, | ||||||||||||
| 174 | FlagPtrToMemberRep = FlagSingleInheritance | FlagMultipleInheritance | | ||||||||||||
| 175 | FlagVirtualInheritance, | ||||||||||||
| 176 | LLVM_MARK_AS_BITMASK_ENUM(FlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = FlagLargest | ||||||||||||
| 177 | }; | ||||||||||||
| 178 | |||||||||||||
| 179 | static DIFlags getFlag(StringRef Flag); | ||||||||||||
| 180 | static StringRef getFlagString(DIFlags Flag); | ||||||||||||
| 181 | |||||||||||||
| 182 | /// Split up a flags bitfield. | ||||||||||||
| 183 | /// | ||||||||||||
| 184 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||||||||||
| 185 | /// any remaining (unrecognized) bits. | ||||||||||||
| 186 | static DIFlags splitFlags(DIFlags Flags, | ||||||||||||
| 187 | SmallVectorImpl<DIFlags> &SplitFlags); | ||||||||||||
| 188 | |||||||||||||
| 189 | static bool classof(const Metadata *MD) { | ||||||||||||
| 190 | switch (MD->getMetadataID()) { | ||||||||||||
| 191 | default: | ||||||||||||
| 192 | return false; | ||||||||||||
| 193 | case GenericDINodeKind: | ||||||||||||
| 194 | case DISubrangeKind: | ||||||||||||
| 195 | case DIEnumeratorKind: | ||||||||||||
| 196 | case DIBasicTypeKind: | ||||||||||||
| 197 | case DIStringTypeKind: | ||||||||||||
| 198 | case DIDerivedTypeKind: | ||||||||||||
| 199 | case DICompositeTypeKind: | ||||||||||||
| 200 | case DISubroutineTypeKind: | ||||||||||||
| 201 | case DIFileKind: | ||||||||||||
| 202 | case DICompileUnitKind: | ||||||||||||
| 203 | case DISubprogramKind: | ||||||||||||
| 204 | case DILexicalBlockKind: | ||||||||||||
| 205 | case DILexicalBlockFileKind: | ||||||||||||
| 206 | case DINamespaceKind: | ||||||||||||
| 207 | case DICommonBlockKind: | ||||||||||||
| 208 | case DITemplateTypeParameterKind: | ||||||||||||
| 209 | case DITemplateValueParameterKind: | ||||||||||||
| 210 | case DIGlobalVariableKind: | ||||||||||||
| 211 | case DILocalVariableKind: | ||||||||||||
| 212 | case DILabelKind: | ||||||||||||
| 213 | case DIObjCPropertyKind: | ||||||||||||
| 214 | case DIImportedEntityKind: | ||||||||||||
| 215 | case DIModuleKind: | ||||||||||||
| 216 | case DIGenericSubrangeKind: | ||||||||||||
| 217 | case DIAssignIDKind: | ||||||||||||
| 218 | return true; | ||||||||||||
| 219 | } | ||||||||||||
| 220 | } | ||||||||||||
| 221 | }; | ||||||||||||
| 222 | |||||||||||||
| 223 | /// Generic tagged DWARF-like metadata node. | ||||||||||||
| 224 | /// | ||||||||||||
| 225 | /// An un-specialized DWARF-like metadata node. The first operand is a | ||||||||||||
| 226 | /// (possibly empty) null-separated \a MDString header that contains arbitrary | ||||||||||||
| 227 | /// fields. The remaining operands are \a dwarf_operands(), and are pointers | ||||||||||||
| 228 | /// to other metadata. | ||||||||||||
| 229 | class GenericDINode : public DINode { | ||||||||||||
| 230 | friend class LLVMContextImpl; | ||||||||||||
| 231 | friend class MDNode; | ||||||||||||
| 232 | |||||||||||||
| 233 | GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, | ||||||||||||
| 234 | unsigned Tag, ArrayRef<Metadata *> Ops1, | ||||||||||||
| 235 | ArrayRef<Metadata *> Ops2) | ||||||||||||
| 236 | : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { | ||||||||||||
| 237 | setHash(Hash); | ||||||||||||
| 238 | } | ||||||||||||
| 239 | ~GenericDINode() { dropAllReferences(); } | ||||||||||||
| 240 | |||||||||||||
| 241 | void setHash(unsigned Hash) { SubclassData32 = Hash; } | ||||||||||||
| 242 | void recalculateHash(); | ||||||||||||
| 243 | |||||||||||||
| 244 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 245 | StringRef Header, ArrayRef<Metadata *> DwarfOps, | ||||||||||||
| 246 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 247 | return getImpl(Context, Tag, getCanonicalMDString(Context, Header), | ||||||||||||
| 248 | DwarfOps, Storage, ShouldCreate); | ||||||||||||
| 249 | } | ||||||||||||
| 250 | |||||||||||||
| 251 | static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 252 | MDString *Header, ArrayRef<Metadata *> DwarfOps, | ||||||||||||
| 253 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 254 | |||||||||||||
| 255 | TempGenericDINode cloneImpl() const { | ||||||||||||
| 256 | return getTemporary(getContext(), getTag(), getHeader(), | ||||||||||||
| 257 | SmallVector<Metadata *, 4>(dwarf_operands())); | ||||||||||||
| 258 | } | ||||||||||||
| 259 | |||||||||||||
| 260 | public: | ||||||||||||
| 261 | unsigned getHash() const { return SubclassData32; } | ||||||||||||
| 262 | |||||||||||||
| 263 | DEFINE_MDNODE_GET(GenericDINode, | ||||||||||||
| 264 | (unsigned Tag, StringRef Header, | ||||||||||||
| 265 | ArrayRef<Metadata *> DwarfOps), | ||||||||||||
| 266 | (Tag, Header, DwarfOps)) | ||||||||||||
| 267 | DEFINE_MDNODE_GET(GenericDINode, | ||||||||||||
| 268 | (unsigned Tag, MDString *Header, | ||||||||||||
| 269 | ArrayRef<Metadata *> DwarfOps), | ||||||||||||
| 270 | (Tag, Header, DwarfOps)) | ||||||||||||
| 271 | |||||||||||||
| 272 | /// Return a (temporary) clone of this. | ||||||||||||
| 273 | TempGenericDINode clone() const { return cloneImpl(); } | ||||||||||||
| 274 | |||||||||||||
| 275 | dwarf::Tag getTag() const; | ||||||||||||
| 276 | StringRef getHeader() const { return getStringOperand(0); } | ||||||||||||
| 277 | MDString *getRawHeader() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 278 | |||||||||||||
| 279 | op_iterator dwarf_op_begin() const { return op_begin() + 1; } | ||||||||||||
| 280 | op_iterator dwarf_op_end() const { return op_end(); } | ||||||||||||
| 281 | op_range dwarf_operands() const { | ||||||||||||
| 282 | return op_range(dwarf_op_begin(), dwarf_op_end()); | ||||||||||||
| 283 | } | ||||||||||||
| 284 | |||||||||||||
| 285 | unsigned getNumDwarfOperands() const { return getNumOperands() - 1; } | ||||||||||||
| 286 | const MDOperand &getDwarfOperand(unsigned I) const { | ||||||||||||
| 287 | return getOperand(I + 1); | ||||||||||||
| 288 | } | ||||||||||||
| 289 | void replaceDwarfOperandWith(unsigned I, Metadata *New) { | ||||||||||||
| 290 | replaceOperandWith(I + 1, New); | ||||||||||||
| 291 | } | ||||||||||||
| 292 | |||||||||||||
| 293 | static bool classof(const Metadata *MD) { | ||||||||||||
| 294 | return MD->getMetadataID() == GenericDINodeKind; | ||||||||||||
| 295 | } | ||||||||||||
| 296 | }; | ||||||||||||
| 297 | |||||||||||||
| 298 | /// Assignment ID. | ||||||||||||
| 299 | /// Used to link stores (as an attachment) and dbg.assigns (as an operand). | ||||||||||||
| 300 | /// DIAssignID metadata is never uniqued as we compare instances using | ||||||||||||
| 301 | /// referential equality (the instance/address is the ID). | ||||||||||||
| 302 | class DIAssignID : public MDNode { | ||||||||||||
| 303 | friend class LLVMContextImpl; | ||||||||||||
| 304 | friend class MDNode; | ||||||||||||
| 305 | |||||||||||||
| 306 | DIAssignID(LLVMContext &C, StorageType Storage) | ||||||||||||
| 307 | : MDNode(C, DIAssignIDKind, Storage, std::nullopt) {} | ||||||||||||
| 308 | |||||||||||||
| 309 | ~DIAssignID() { dropAllReferences(); } | ||||||||||||
| 310 | |||||||||||||
| 311 | static DIAssignID *getImpl(LLVMContext &Context, StorageType Storage, | ||||||||||||
| 312 | bool ShouldCreate = true); | ||||||||||||
| 313 | |||||||||||||
| 314 | TempDIAssignID cloneImpl() const { return getTemporary(getContext()); } | ||||||||||||
| 315 | |||||||||||||
| 316 | public: | ||||||||||||
| 317 | // This node has no operands to replace. | ||||||||||||
| 318 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||||||||||
| 319 | |||||||||||||
| 320 | static DIAssignID *getDistinct(LLVMContext &Context) { | ||||||||||||
| 321 | return getImpl(Context, Distinct); | ||||||||||||
| 322 | } | ||||||||||||
| 323 | static TempDIAssignID getTemporary(LLVMContext &Context) { | ||||||||||||
| 324 | return TempDIAssignID(getImpl(Context, Temporary)); | ||||||||||||
| 325 | } | ||||||||||||
| 326 | // NOTE: Do not define get(LLVMContext&) - see class comment. | ||||||||||||
| 327 | |||||||||||||
| 328 | static bool classof(const Metadata *MD) { | ||||||||||||
| 329 | return MD->getMetadataID() == DIAssignIDKind; | ||||||||||||
| 330 | } | ||||||||||||
| 331 | }; | ||||||||||||
| 332 | |||||||||||||
| 333 | /// Array subrange. | ||||||||||||
| 334 | /// | ||||||||||||
| 335 | /// TODO: Merge into node for DW_TAG_array_type, which should have a custom | ||||||||||||
| 336 | /// type. | ||||||||||||
| 337 | class DISubrange : public DINode { | ||||||||||||
| 338 | friend class LLVMContextImpl; | ||||||||||||
| 339 | friend class MDNode; | ||||||||||||
| 340 | |||||||||||||
| 341 | DISubrange(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops); | ||||||||||||
| 342 | |||||||||||||
| 343 | ~DISubrange() = default; | ||||||||||||
| 344 | |||||||||||||
| 345 | static DISubrange *getImpl(LLVMContext &Context, int64_t Count, | ||||||||||||
| 346 | int64_t LowerBound, StorageType Storage, | ||||||||||||
| 347 | bool ShouldCreate = true); | ||||||||||||
| 348 | |||||||||||||
| 349 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
| 350 | int64_t LowerBound, StorageType Storage, | ||||||||||||
| 351 | bool ShouldCreate = true); | ||||||||||||
| 352 | |||||||||||||
| 353 | static DISubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
| 354 | Metadata *LowerBound, Metadata *UpperBound, | ||||||||||||
| 355 | Metadata *Stride, StorageType Storage, | ||||||||||||
| 356 | bool ShouldCreate = true); | ||||||||||||
| 357 | |||||||||||||
| 358 | TempDISubrange cloneImpl() const { | ||||||||||||
| 359 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||||||||||
| 360 | getRawUpperBound(), getRawStride()); | ||||||||||||
| 361 | } | ||||||||||||
| 362 | |||||||||||||
| 363 | public: | ||||||||||||
| 364 | DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), | ||||||||||||
| 365 | (Count, LowerBound)) | ||||||||||||
| 366 | |||||||||||||
| 367 | DEFINE_MDNODE_GET(DISubrange, (Metadata * CountNode, int64_t LowerBound = 0), | ||||||||||||
| 368 | (CountNode, LowerBound)) | ||||||||||||
| 369 | |||||||||||||
| 370 | DEFINE_MDNODE_GET(DISubrange, | ||||||||||||
| 371 | (Metadata * CountNode, Metadata *LowerBound, | ||||||||||||
| 372 | Metadata *UpperBound, Metadata *Stride), | ||||||||||||
| 373 | (CountNode, LowerBound, UpperBound, Stride)) | ||||||||||||
| 374 | |||||||||||||
| 375 | TempDISubrange clone() const { return cloneImpl(); } | ||||||||||||
| 376 | |||||||||||||
| 377 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||||||||||
| 378 | |||||||||||||
| 379 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||||||||||
| 380 | |||||||||||||
| 381 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||||||||||
| 382 | |||||||||||||
| 383 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||||||||||
| 384 | |||||||||||||
| 385 | typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType; | ||||||||||||
| 386 | |||||||||||||
| 387 | BoundType getCount() const; | ||||||||||||
| 388 | |||||||||||||
| 389 | BoundType getLowerBound() const; | ||||||||||||
| 390 | |||||||||||||
| 391 | BoundType getUpperBound() const; | ||||||||||||
| 392 | |||||||||||||
| 393 | BoundType getStride() const; | ||||||||||||
| 394 | |||||||||||||
| 395 | static bool classof(const Metadata *MD) { | ||||||||||||
| 396 | return MD->getMetadataID() == DISubrangeKind; | ||||||||||||
| 397 | } | ||||||||||||
| 398 | }; | ||||||||||||
| 399 | |||||||||||||
| 400 | class DIGenericSubrange : public DINode { | ||||||||||||
| 401 | friend class LLVMContextImpl; | ||||||||||||
| 402 | friend class MDNode; | ||||||||||||
| 403 | |||||||||||||
| 404 | DIGenericSubrange(LLVMContext &C, StorageType Storage, | ||||||||||||
| 405 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 406 | |||||||||||||
| 407 | ~DIGenericSubrange() = default; | ||||||||||||
| 408 | |||||||||||||
| 409 | static DIGenericSubrange *getImpl(LLVMContext &Context, Metadata *CountNode, | ||||||||||||
| 410 | Metadata *LowerBound, Metadata *UpperBound, | ||||||||||||
| 411 | Metadata *Stride, StorageType Storage, | ||||||||||||
| 412 | bool ShouldCreate = true); | ||||||||||||
| 413 | |||||||||||||
| 414 | TempDIGenericSubrange cloneImpl() const { | ||||||||||||
| 415 | return getTemporary(getContext(), getRawCountNode(), getRawLowerBound(), | ||||||||||||
| 416 | getRawUpperBound(), getRawStride()); | ||||||||||||
| 417 | } | ||||||||||||
| 418 | |||||||||||||
| 419 | public: | ||||||||||||
| 420 | DEFINE_MDNODE_GET(DIGenericSubrange, | ||||||||||||
| 421 | (Metadata * CountNode, Metadata *LowerBound, | ||||||||||||
| 422 | Metadata *UpperBound, Metadata *Stride), | ||||||||||||
| 423 | (CountNode, LowerBound, UpperBound, Stride)) | ||||||||||||
| 424 | |||||||||||||
| 425 | TempDIGenericSubrange clone() const { return cloneImpl(); } | ||||||||||||
| 426 | |||||||||||||
| 427 | Metadata *getRawCountNode() const { return getOperand(0).get(); } | ||||||||||||
| 428 | Metadata *getRawLowerBound() const { return getOperand(1).get(); } | ||||||||||||
| 429 | Metadata *getRawUpperBound() const { return getOperand(2).get(); } | ||||||||||||
| 430 | Metadata *getRawStride() const { return getOperand(3).get(); } | ||||||||||||
| 431 | |||||||||||||
| 432 | using BoundType = PointerUnion<DIVariable *, DIExpression *>; | ||||||||||||
| 433 | |||||||||||||
| 434 | BoundType getCount() const; | ||||||||||||
| 435 | BoundType getLowerBound() const; | ||||||||||||
| 436 | BoundType getUpperBound() const; | ||||||||||||
| 437 | BoundType getStride() const; | ||||||||||||
| 438 | |||||||||||||
| 439 | static bool classof(const Metadata *MD) { | ||||||||||||
| 440 | return MD->getMetadataID() == DIGenericSubrangeKind; | ||||||||||||
| 441 | } | ||||||||||||
| 442 | }; | ||||||||||||
| 443 | |||||||||||||
| 444 | /// Enumeration value. | ||||||||||||
| 445 | /// | ||||||||||||
| 446 | /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no | ||||||||||||
| 447 | /// longer creates a type cycle. | ||||||||||||
| 448 | class DIEnumerator : public DINode { | ||||||||||||
| 449 | friend class LLVMContextImpl; | ||||||||||||
| 450 | friend class MDNode; | ||||||||||||
| 451 | |||||||||||||
| 452 | APInt Value; | ||||||||||||
| 453 | DIEnumerator(LLVMContext &C, StorageType Storage, const APInt &Value, | ||||||||||||
| 454 | bool IsUnsigned, ArrayRef<Metadata *> Ops); | ||||||||||||
| 455 | DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, | ||||||||||||
| 456 | bool IsUnsigned, ArrayRef<Metadata *> Ops) | ||||||||||||
| 457 | : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, | ||||||||||||
| 458 | Ops) {} | ||||||||||||
| 459 | ~DIEnumerator() = default; | ||||||||||||
| 460 | |||||||||||||
| 461 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||||||||||
| 462 | bool IsUnsigned, StringRef Name, | ||||||||||||
| 463 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 464 | return getImpl(Context, Value, IsUnsigned, | ||||||||||||
| 465 | getCanonicalMDString(Context, Name), Storage, ShouldCreate); | ||||||||||||
| 466 | } | ||||||||||||
| 467 | static DIEnumerator *getImpl(LLVMContext &Context, const APInt &Value, | ||||||||||||
| 468 | bool IsUnsigned, MDString *Name, | ||||||||||||
| 469 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 470 | |||||||||||||
| 471 | TempDIEnumerator cloneImpl() const { | ||||||||||||
| 472 | return getTemporary(getContext(), getValue(), isUnsigned(), getName()); | ||||||||||||
| 473 | } | ||||||||||||
| 474 | |||||||||||||
| 475 | public: | ||||||||||||
| 476 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
| 477 | (int64_t Value, bool IsUnsigned, StringRef Name), | ||||||||||||
| 478 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||||||||||
| 479 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
| 480 | (int64_t Value, bool IsUnsigned, MDString *Name), | ||||||||||||
| 481 | (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) | ||||||||||||
| 482 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
| 483 | (APInt Value, bool IsUnsigned, StringRef Name), | ||||||||||||
| 484 | (Value, IsUnsigned, Name)) | ||||||||||||
| 485 | DEFINE_MDNODE_GET(DIEnumerator, | ||||||||||||
| 486 | (APInt Value, bool IsUnsigned, MDString *Name), | ||||||||||||
| 487 | (Value, IsUnsigned, Name)) | ||||||||||||
| 488 | |||||||||||||
| 489 | TempDIEnumerator clone() const { return cloneImpl(); } | ||||||||||||
| 490 | |||||||||||||
| 491 | const APInt &getValue() const { return Value; } | ||||||||||||
| 492 | bool isUnsigned() const { return SubclassData32; } | ||||||||||||
| 493 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
| 494 | |||||||||||||
| 495 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 496 | |||||||||||||
| 497 | static bool classof(const Metadata *MD) { | ||||||||||||
| 498 | return MD->getMetadataID() == DIEnumeratorKind; | ||||||||||||
| 499 | } | ||||||||||||
| 500 | }; | ||||||||||||
| 501 | |||||||||||||
| 502 | /// Base class for scope-like contexts. | ||||||||||||
| 503 | /// | ||||||||||||
| 504 | /// Base class for lexical scopes and types (which are also declaration | ||||||||||||
| 505 | /// contexts). | ||||||||||||
| 506 | /// | ||||||||||||
| 507 | /// TODO: Separate the concepts of declaration contexts and lexical scopes. | ||||||||||||
| 508 | class DIScope : public DINode { | ||||||||||||
| 509 | protected: | ||||||||||||
| 510 | DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
| 511 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 512 | : DINode(C, ID, Storage, Tag, Ops) {} | ||||||||||||
| 513 | ~DIScope() = default; | ||||||||||||
| 514 | |||||||||||||
| 515 | public: | ||||||||||||
| 516 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 517 | |||||||||||||
| 518 | inline StringRef getFilename() const; | ||||||||||||
| 519 | inline StringRef getDirectory() const; | ||||||||||||
| 520 | inline std::optional<StringRef> getSource() const; | ||||||||||||
| 521 | |||||||||||||
| 522 | StringRef getName() const; | ||||||||||||
| 523 | DIScope *getScope() const; | ||||||||||||
| 524 | |||||||||||||
| 525 | /// Return the raw underlying file. | ||||||||||||
| 526 | /// | ||||||||||||
| 527 | /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it | ||||||||||||
| 528 | /// \em is the file). If \c this is an \a DIFile, we need to return \c this. | ||||||||||||
| 529 | /// Otherwise, return the first operand, which is where all other subclasses | ||||||||||||
| 530 | /// store their file pointer. | ||||||||||||
| 531 | Metadata *getRawFile() const { | ||||||||||||
| 532 | return isa<DIFile>(this) ? const_cast<DIScope *>(this) | ||||||||||||
| 533 | : static_cast<Metadata *>(getOperand(0)); | ||||||||||||
| 534 | } | ||||||||||||
| 535 | |||||||||||||
| 536 | static bool classof(const Metadata *MD) { | ||||||||||||
| 537 | switch (MD->getMetadataID()) { | ||||||||||||
| 538 | default: | ||||||||||||
| 539 | return false; | ||||||||||||
| 540 | case DIBasicTypeKind: | ||||||||||||
| 541 | case DIStringTypeKind: | ||||||||||||
| 542 | case DIDerivedTypeKind: | ||||||||||||
| 543 | case DICompositeTypeKind: | ||||||||||||
| 544 | case DISubroutineTypeKind: | ||||||||||||
| 545 | case DIFileKind: | ||||||||||||
| 546 | case DICompileUnitKind: | ||||||||||||
| 547 | case DISubprogramKind: | ||||||||||||
| 548 | case DILexicalBlockKind: | ||||||||||||
| 549 | case DILexicalBlockFileKind: | ||||||||||||
| 550 | case DINamespaceKind: | ||||||||||||
| 551 | case DICommonBlockKind: | ||||||||||||
| 552 | case DIModuleKind: | ||||||||||||
| 553 | return true; | ||||||||||||
| 554 | } | ||||||||||||
| 555 | } | ||||||||||||
| 556 | }; | ||||||||||||
| 557 | |||||||||||||
| 558 | /// File. | ||||||||||||
| 559 | /// | ||||||||||||
| 560 | /// TODO: Merge with directory/file node (including users). | ||||||||||||
| 561 | /// TODO: Canonicalize paths on creation. | ||||||||||||
| 562 | class DIFile : public DIScope { | ||||||||||||
| 563 | friend class LLVMContextImpl; | ||||||||||||
| 564 | friend class MDNode; | ||||||||||||
| 565 | |||||||||||||
| 566 | public: | ||||||||||||
| 567 | /// Which algorithm (e.g. MD5) a checksum was generated with. | ||||||||||||
| 568 | /// | ||||||||||||
| 569 | /// The encoding is explicit because it is used directly in Bitcode. The | ||||||||||||
| 570 | /// value 0 is reserved to indicate the absence of a checksum in Bitcode. | ||||||||||||
| 571 | enum ChecksumKind { | ||||||||||||
| 572 | // The first variant was originally CSK_None, encoded as 0. The new | ||||||||||||
| 573 | // internal representation removes the need for this by wrapping the | ||||||||||||
| 574 | // ChecksumInfo in an Optional, but to preserve Bitcode compatibility the 0 | ||||||||||||
| 575 | // encoding is reserved. | ||||||||||||
| 576 | CSK_MD5 = 1, | ||||||||||||
| 577 | CSK_SHA1 = 2, | ||||||||||||
| 578 | CSK_SHA256 = 3, | ||||||||||||
| 579 | CSK_Last = CSK_SHA256 // Should be last enumeration. | ||||||||||||
| 580 | }; | ||||||||||||
| 581 | |||||||||||||
| 582 | /// A single checksum, represented by a \a Kind and a \a Value (a string). | ||||||||||||
| 583 | template <typename T> struct ChecksumInfo { | ||||||||||||
| 584 | /// The kind of checksum which \a Value encodes. | ||||||||||||
| 585 | ChecksumKind Kind; | ||||||||||||
| 586 | /// The string value of the checksum. | ||||||||||||
| 587 | T Value; | ||||||||||||
| 588 | |||||||||||||
| 589 | ChecksumInfo(ChecksumKind Kind, T Value) : Kind(Kind), Value(Value) {} | ||||||||||||
| 590 | ~ChecksumInfo() = default; | ||||||||||||
| 591 | bool operator==(const ChecksumInfo<T> &X) const { | ||||||||||||
| 592 | return Kind == X.Kind && Value == X.Value; | ||||||||||||
| 593 | } | ||||||||||||
| 594 | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | ||||||||||||
| 595 | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | ||||||||||||
| 596 | }; | ||||||||||||
| 597 | |||||||||||||
| 598 | private: | ||||||||||||
| 599 | std::optional<ChecksumInfo<MDString *>> Checksum; | ||||||||||||
| 600 | /// An optional source. A nullptr means none. | ||||||||||||
| 601 | MDString *Source; | ||||||||||||
| 602 | |||||||||||||
| 603 | DIFile(LLVMContext &C, StorageType Storage, | ||||||||||||
| 604 | std::optional<ChecksumInfo<MDString *>> CS, MDString *Src, | ||||||||||||
| 605 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 606 | ~DIFile() = default; | ||||||||||||
| 607 | |||||||||||||
| 608 | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | ||||||||||||
| 609 | StringRef Directory, | ||||||||||||
| 610 | std::optional<ChecksumInfo<StringRef>> CS, | ||||||||||||
| 611 | std::optional<StringRef> Source, StorageType Storage, | ||||||||||||
| 612 | bool ShouldCreate = true) { | ||||||||||||
| 613 | std::optional<ChecksumInfo<MDString *>> MDChecksum; | ||||||||||||
| 614 | if (CS) | ||||||||||||
| 615 | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | ||||||||||||
| 616 | return getImpl(Context, getCanonicalMDString(Context, Filename), | ||||||||||||
| 617 | getCanonicalMDString(Context, Directory), MDChecksum, | ||||||||||||
| 618 | Source ? MDString::get(Context, *Source) : nullptr, Storage, | ||||||||||||
| 619 | ShouldCreate); | ||||||||||||
| 620 | } | ||||||||||||
| 621 | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | ||||||||||||
| 622 | MDString *Directory, | ||||||||||||
| 623 | std::optional<ChecksumInfo<MDString *>> CS, | ||||||||||||
| 624 | MDString *Source, StorageType Storage, | ||||||||||||
| 625 | bool ShouldCreate = true); | ||||||||||||
| 626 | |||||||||||||
| 627 | TempDIFile cloneImpl() const { | ||||||||||||
| 628 | return getTemporary(getContext(), getFilename(), getDirectory(), | ||||||||||||
| 629 | getChecksum(), getSource()); | ||||||||||||
| 630 | } | ||||||||||||
| 631 | |||||||||||||
| 632 | public: | ||||||||||||
| 633 | DEFINE_MDNODE_GET(DIFile, | ||||||||||||
| 634 | (StringRef Filename, StringRef Directory, | ||||||||||||
| 635 | std::optional<ChecksumInfo<StringRef>> CS = std::nullopt, | ||||||||||||
| 636 | std::optional<StringRef> Source = std::nullopt), | ||||||||||||
| 637 | (Filename, Directory, CS, Source)) | ||||||||||||
| 638 | DEFINE_MDNODE_GET(DIFile, | ||||||||||||
| 639 | (MDString * Filename, MDString *Directory, | ||||||||||||
| 640 | std::optional<ChecksumInfo<MDString *>> CS = std::nullopt, | ||||||||||||
| 641 | MDString *Source = nullptr), | ||||||||||||
| 642 | (Filename, Directory, CS, Source)) | ||||||||||||
| 643 | |||||||||||||
| 644 | TempDIFile clone() const { return cloneImpl(); } | ||||||||||||
| 645 | |||||||||||||
| 646 | StringRef getFilename() const { return getStringOperand(0); } | ||||||||||||
| 647 | StringRef getDirectory() const { return getStringOperand(1); } | ||||||||||||
| 648 | std::optional<ChecksumInfo<StringRef>> getChecksum() const { | ||||||||||||
| 649 | std::optional<ChecksumInfo<StringRef>> StringRefChecksum; | ||||||||||||
| 650 | if (Checksum) | ||||||||||||
| 651 | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | ||||||||||||
| 652 | return StringRefChecksum; | ||||||||||||
| 653 | } | ||||||||||||
| 654 | std::optional<StringRef> getSource() const { | ||||||||||||
| 655 | return Source ? std::optional<StringRef>(Source->getString()) | ||||||||||||
| 656 | : std::nullopt; | ||||||||||||
| 657 | } | ||||||||||||
| 658 | |||||||||||||
| 659 | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 660 | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | ||||||||||||
| 661 | std::optional<ChecksumInfo<MDString *>> getRawChecksum() const { | ||||||||||||
| 662 | return Checksum; | ||||||||||||
| 663 | } | ||||||||||||
| 664 | MDString *getRawSource() const { return Source; } | ||||||||||||
| 665 | |||||||||||||
| 666 | static StringRef getChecksumKindAsString(ChecksumKind CSKind); | ||||||||||||
| 667 | static std::optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | ||||||||||||
| 668 | |||||||||||||
| 669 | static bool classof(const Metadata *MD) { | ||||||||||||
| 670 | return MD->getMetadataID() == DIFileKind; | ||||||||||||
| 671 | } | ||||||||||||
| 672 | }; | ||||||||||||
| 673 | |||||||||||||
| 674 | StringRef DIScope::getFilename() const { | ||||||||||||
| 675 | if (auto *F = getFile()) | ||||||||||||
| 676 | return F->getFilename(); | ||||||||||||
| 677 | return ""; | ||||||||||||
| 678 | } | ||||||||||||
| 679 | |||||||||||||
| 680 | StringRef DIScope::getDirectory() const { | ||||||||||||
| 681 | if (auto *F = getFile()) | ||||||||||||
| 682 | return F->getDirectory(); | ||||||||||||
| 683 | return ""; | ||||||||||||
| 684 | } | ||||||||||||
| 685 | |||||||||||||
| 686 | std::optional<StringRef> DIScope::getSource() const { | ||||||||||||
| 687 | if (auto *F = getFile()) | ||||||||||||
| 688 | return F->getSource(); | ||||||||||||
| 689 | return std::nullopt; | ||||||||||||
| 690 | } | ||||||||||||
| 691 | |||||||||||||
| 692 | /// Base class for types. | ||||||||||||
| 693 | /// | ||||||||||||
| 694 | /// TODO: Remove the hardcoded name and context, since many types don't use | ||||||||||||
| 695 | /// them. | ||||||||||||
| 696 | /// TODO: Split up flags. | ||||||||||||
| 697 | class DIType : public DIScope { | ||||||||||||
| 698 | unsigned Line; | ||||||||||||
| 699 | DIFlags Flags; | ||||||||||||
| 700 | uint64_t SizeInBits; | ||||||||||||
| 701 | uint64_t OffsetInBits; | ||||||||||||
| 702 | uint32_t AlignInBits; | ||||||||||||
| 703 | |||||||||||||
| 704 | protected: | ||||||||||||
| 705 | DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
| 706 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 707 | uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||||||||||
| 708 | : DIScope(C, ID, Storage, Tag, Ops) { | ||||||||||||
| 709 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
| 710 | } | ||||||||||||
| 711 | ~DIType() = default; | ||||||||||||
| 712 | |||||||||||||
| 713 | void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 714 | uint64_t OffsetInBits, DIFlags Flags) { | ||||||||||||
| 715 | this->Line = Line; | ||||||||||||
| 716 | this->Flags = Flags; | ||||||||||||
| 717 | this->SizeInBits = SizeInBits; | ||||||||||||
| 718 | this->AlignInBits = AlignInBits; | ||||||||||||
| 719 | this->OffsetInBits = OffsetInBits; | ||||||||||||
| 720 | } | ||||||||||||
| 721 | |||||||||||||
| 722 | /// Change fields in place. | ||||||||||||
| 723 | void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits, | ||||||||||||
| 724 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) { | ||||||||||||
| 725 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 725, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 726 | setTag(Tag); | ||||||||||||
| 727 | init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
| 728 | } | ||||||||||||
| 729 | |||||||||||||
| 730 | public: | ||||||||||||
| 731 | TempDIType clone() const { | ||||||||||||
| 732 | return TempDIType(cast<DIType>(MDNode::clone().release())); | ||||||||||||
| 733 | } | ||||||||||||
| 734 | |||||||||||||
| 735 | unsigned getLine() const { return Line; } | ||||||||||||
| 736 | uint64_t getSizeInBits() const { return SizeInBits; } | ||||||||||||
| 737 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||||||||||
| 738 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||||||||||
| 739 | uint64_t getOffsetInBits() const { return OffsetInBits; } | ||||||||||||
| 740 | DIFlags getFlags() const { return Flags; } | ||||||||||||
| 741 | |||||||||||||
| 742 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 743 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 744 | |||||||||||||
| 745 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
| 746 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 747 | |||||||||||||
| 748 | /// Returns a new temporary DIType with updated Flags | ||||||||||||
| 749 | TempDIType cloneWithFlags(DIFlags NewFlags) const { | ||||||||||||
| 750 | auto NewTy = clone(); | ||||||||||||
| 751 | NewTy->Flags = NewFlags; | ||||||||||||
| 752 | return NewTy; | ||||||||||||
| 753 | } | ||||||||||||
| 754 | |||||||||||||
| 755 | bool isPrivate() const { | ||||||||||||
| 756 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||||||||||
| 757 | } | ||||||||||||
| 758 | bool isProtected() const { | ||||||||||||
| 759 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||||||||||
| 760 | } | ||||||||||||
| 761 | bool isPublic() const { | ||||||||||||
| 762 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||||||||||
| 763 | } | ||||||||||||
| 764 | bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } | ||||||||||||
| 765 | bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } | ||||||||||||
| 766 | bool isVirtual() const { return getFlags() & FlagVirtual; } | ||||||||||||
| 767 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
| 768 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||||||||||
| 769 | bool isObjcClassComplete() const { | ||||||||||||
| 770 | return getFlags() & FlagObjcClassComplete; | ||||||||||||
| 771 | } | ||||||||||||
| 772 | bool isVector() const { return getFlags() & FlagVector; } | ||||||||||||
| 773 | bool isBitField() const { return getFlags() & FlagBitField; } | ||||||||||||
| 774 | bool isStaticMember() const { return getFlags() & FlagStaticMember; } | ||||||||||||
| 775 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||||||||||
| 776 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||||||||||
| 777 | bool isTypePassByValue() const { return getFlags() & FlagTypePassByValue; } | ||||||||||||
| 778 | bool isTypePassByReference() const { | ||||||||||||
| 779 | return getFlags() & FlagTypePassByReference; | ||||||||||||
| 780 | } | ||||||||||||
| 781 | bool isBigEndian() const { return getFlags() & FlagBigEndian; } | ||||||||||||
| 782 | bool isLittleEndian() const { return getFlags() & FlagLittleEndian; } | ||||||||||||
| 783 | bool getExportSymbols() const { return getFlags() & FlagExportSymbols; } | ||||||||||||
| 784 | |||||||||||||
| 785 | static bool classof(const Metadata *MD) { | ||||||||||||
| 786 | switch (MD->getMetadataID()) { | ||||||||||||
| 787 | default: | ||||||||||||
| 788 | return false; | ||||||||||||
| 789 | case DIBasicTypeKind: | ||||||||||||
| 790 | case DIStringTypeKind: | ||||||||||||
| 791 | case DIDerivedTypeKind: | ||||||||||||
| 792 | case DICompositeTypeKind: | ||||||||||||
| 793 | case DISubroutineTypeKind: | ||||||||||||
| 794 | return true; | ||||||||||||
| 795 | } | ||||||||||||
| 796 | } | ||||||||||||
| 797 | }; | ||||||||||||
| 798 | |||||||||||||
| 799 | /// Basic type, like 'int' or 'float'. | ||||||||||||
| 800 | /// | ||||||||||||
| 801 | /// TODO: Split out DW_TAG_unspecified_type. | ||||||||||||
| 802 | /// TODO: Drop unused accessors. | ||||||||||||
| 803 | class DIBasicType : public DIType { | ||||||||||||
| 804 | friend class LLVMContextImpl; | ||||||||||||
| 805 | friend class MDNode; | ||||||||||||
| 806 | |||||||||||||
| 807 | unsigned Encoding; | ||||||||||||
| 808 | |||||||||||||
| 809 | DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
| 810 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
| 811 | DIFlags Flags, ArrayRef<Metadata *> Ops) | ||||||||||||
| 812 | : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||||||||||
| 813 | Flags, Ops), | ||||||||||||
| 814 | Encoding(Encoding) {} | ||||||||||||
| 815 | ~DIBasicType() = default; | ||||||||||||
| 816 | |||||||||||||
| 817 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 818 | StringRef Name, uint64_t SizeInBits, | ||||||||||||
| 819 | uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
| 820 | DIFlags Flags, StorageType Storage, | ||||||||||||
| 821 | bool ShouldCreate = true) { | ||||||||||||
| 822 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||||||||||
| 823 | SizeInBits, AlignInBits, Encoding, Flags, Storage, | ||||||||||||
| 824 | ShouldCreate); | ||||||||||||
| 825 | } | ||||||||||||
| 826 | static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 827 | MDString *Name, uint64_t SizeInBits, | ||||||||||||
| 828 | uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
| 829 | DIFlags Flags, StorageType Storage, | ||||||||||||
| 830 | bool ShouldCreate = true); | ||||||||||||
| 831 | |||||||||||||
| 832 | TempDIBasicType cloneImpl() const { | ||||||||||||
| 833 | return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), | ||||||||||||
| 834 | getAlignInBits(), getEncoding(), getFlags()); | ||||||||||||
| 835 | } | ||||||||||||
| 836 | |||||||||||||
| 837 | public: | ||||||||||||
| 838 | DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), | ||||||||||||
| 839 | (Tag, Name, 0, 0, 0, FlagZero)) | ||||||||||||
| 840 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
| 841 | (unsigned Tag, StringRef Name, uint64_t SizeInBits), | ||||||||||||
| 842 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||||||||||
| 843 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
| 844 | (unsigned Tag, MDString *Name, uint64_t SizeInBits), | ||||||||||||
| 845 | (Tag, Name, SizeInBits, 0, 0, FlagZero)) | ||||||||||||
| 846 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
| 847 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||||||||||
| 848 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||||||||||
| 849 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||||||||||
| 850 | DEFINE_MDNODE_GET(DIBasicType, | ||||||||||||
| 851 | (unsigned Tag, MDString *Name, uint64_t SizeInBits, | ||||||||||||
| 852 | uint32_t AlignInBits, unsigned Encoding, DIFlags Flags), | ||||||||||||
| 853 | (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags)) | ||||||||||||
| 854 | |||||||||||||
| 855 | TempDIBasicType clone() const { return cloneImpl(); } | ||||||||||||
| 856 | |||||||||||||
| 857 | unsigned getEncoding() const { return Encoding; } | ||||||||||||
| 858 | |||||||||||||
| 859 | enum class Signedness { Signed, Unsigned }; | ||||||||||||
| 860 | |||||||||||||
| 861 | /// Return the signedness of this type, or std::nullopt if this type is | ||||||||||||
| 862 | /// neither signed nor unsigned. | ||||||||||||
| 863 | std::optional<Signedness> getSignedness() const; | ||||||||||||
| 864 | |||||||||||||
| 865 | static bool classof(const Metadata *MD) { | ||||||||||||
| 866 | return MD->getMetadataID() == DIBasicTypeKind; | ||||||||||||
| 867 | } | ||||||||||||
| 868 | }; | ||||||||||||
| 869 | |||||||||||||
| 870 | /// String type, Fortran CHARACTER(n) | ||||||||||||
| 871 | class DIStringType : public DIType { | ||||||||||||
| 872 | friend class LLVMContextImpl; | ||||||||||||
| 873 | friend class MDNode; | ||||||||||||
| 874 | |||||||||||||
| 875 | unsigned Encoding; | ||||||||||||
| 876 | |||||||||||||
| 877 | DIStringType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
| 878 | uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding, | ||||||||||||
| 879 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 880 | : DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, | ||||||||||||
| 881 | FlagZero, Ops), | ||||||||||||
| 882 | Encoding(Encoding) {} | ||||||||||||
| 883 | ~DIStringType() = default; | ||||||||||||
| 884 | |||||||||||||
| 885 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 886 | StringRef Name, Metadata *StringLength, | ||||||||||||
| 887 | Metadata *StrLenExp, Metadata *StrLocationExp, | ||||||||||||
| 888 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 889 | unsigned Encoding, StorageType Storage, | ||||||||||||
| 890 | bool ShouldCreate = true) { | ||||||||||||
| 891 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), | ||||||||||||
| 892 | StringLength, StrLenExp, StrLocationExp, SizeInBits, | ||||||||||||
| 893 | AlignInBits, Encoding, Storage, ShouldCreate); | ||||||||||||
| 894 | } | ||||||||||||
| 895 | static DIStringType *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 896 | MDString *Name, Metadata *StringLength, | ||||||||||||
| 897 | Metadata *StrLenExp, Metadata *StrLocationExp, | ||||||||||||
| 898 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 899 | unsigned Encoding, StorageType Storage, | ||||||||||||
| 900 | bool ShouldCreate = true); | ||||||||||||
| 901 | |||||||||||||
| 902 | TempDIStringType cloneImpl() const { | ||||||||||||
| 903 | return getTemporary(getContext(), getTag(), getRawName(), | ||||||||||||
| 904 | getRawStringLength(), getRawStringLengthExp(), | ||||||||||||
| 905 | getRawStringLocationExp(), getSizeInBits(), | ||||||||||||
| 906 | getAlignInBits(), getEncoding()); | ||||||||||||
| 907 | } | ||||||||||||
| 908 | |||||||||||||
| 909 | public: | ||||||||||||
| 910 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
| 911 | (unsigned Tag, StringRef Name, uint64_t SizeInBits, | ||||||||||||
| 912 | uint32_t AlignInBits), | ||||||||||||
| 913 | (Tag, Name, nullptr, nullptr, nullptr, SizeInBits, | ||||||||||||
| 914 | AlignInBits, 0)) | ||||||||||||
| 915 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
| 916 | (unsigned Tag, MDString *Name, Metadata *StringLength, | ||||||||||||
| 917 | Metadata *StringLengthExp, Metadata *StringLocationExp, | ||||||||||||
| 918 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 919 | unsigned Encoding), | ||||||||||||
| 920 | (Tag, Name, StringLength, StringLengthExp, | ||||||||||||
| 921 | StringLocationExp, SizeInBits, AlignInBits, Encoding)) | ||||||||||||
| 922 | DEFINE_MDNODE_GET(DIStringType, | ||||||||||||
| 923 | (unsigned Tag, StringRef Name, Metadata *StringLength, | ||||||||||||
| 924 | Metadata *StringLengthExp, Metadata *StringLocationExp, | ||||||||||||
| 925 | uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 926 | unsigned Encoding), | ||||||||||||
| 927 | (Tag, Name, StringLength, StringLengthExp, | ||||||||||||
| 928 | StringLocationExp, SizeInBits, AlignInBits, Encoding)) | ||||||||||||
| 929 | |||||||||||||
| 930 | TempDIStringType clone() const { return cloneImpl(); } | ||||||||||||
| 931 | |||||||||||||
| 932 | static bool classof(const Metadata *MD) { | ||||||||||||
| 933 | return MD->getMetadataID() == DIStringTypeKind; | ||||||||||||
| 934 | } | ||||||||||||
| 935 | |||||||||||||
| 936 | DIVariable *getStringLength() const { | ||||||||||||
| 937 | return cast_or_null<DIVariable>(getRawStringLength()); | ||||||||||||
| 938 | } | ||||||||||||
| 939 | |||||||||||||
| 940 | DIExpression *getStringLengthExp() const { | ||||||||||||
| 941 | return cast_or_null<DIExpression>(getRawStringLengthExp()); | ||||||||||||
| 942 | } | ||||||||||||
| 943 | |||||||||||||
| 944 | DIExpression *getStringLocationExp() const { | ||||||||||||
| 945 | return cast_or_null<DIExpression>(getRawStringLocationExp()); | ||||||||||||
| 946 | } | ||||||||||||
| 947 | |||||||||||||
| 948 | unsigned getEncoding() const { return Encoding; } | ||||||||||||
| 949 | |||||||||||||
| 950 | Metadata *getRawStringLength() const { return getOperand(3); } | ||||||||||||
| 951 | |||||||||||||
| 952 | Metadata *getRawStringLengthExp() const { return getOperand(4); } | ||||||||||||
| 953 | |||||||||||||
| 954 | Metadata *getRawStringLocationExp() const { return getOperand(5); } | ||||||||||||
| 955 | }; | ||||||||||||
| 956 | |||||||||||||
| 957 | /// Derived types. | ||||||||||||
| 958 | /// | ||||||||||||
| 959 | /// This includes qualified types, pointers, references, friends, typedefs, and | ||||||||||||
| 960 | /// class members. | ||||||||||||
| 961 | /// | ||||||||||||
| 962 | /// TODO: Split out members (inheritance, fields, methods, etc.). | ||||||||||||
| 963 | class DIDerivedType : public DIType { | ||||||||||||
| 964 | friend class LLVMContextImpl; | ||||||||||||
| 965 | friend class MDNode; | ||||||||||||
| 966 | |||||||||||||
| 967 | /// The DWARF address space of the memory pointed to or referenced by a | ||||||||||||
| 968 | /// pointer or reference type respectively. | ||||||||||||
| 969 | std::optional<unsigned> DWARFAddressSpace; | ||||||||||||
| 970 | |||||||||||||
| 971 | DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
| 972 | unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 973 | uint64_t OffsetInBits, | ||||||||||||
| 974 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
| 975 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 976 | : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, | ||||||||||||
| 977 | AlignInBits, OffsetInBits, Flags, Ops), | ||||||||||||
| 978 | DWARFAddressSpace(DWARFAddressSpace) {} | ||||||||||||
| 979 | ~DIDerivedType() = default; | ||||||||||||
| 980 | static DIDerivedType * | ||||||||||||
| 981 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, DIFile *File, | ||||||||||||
| 982 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
| 983 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 984 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
| 985 | Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, | ||||||||||||
| 986 | bool ShouldCreate = true) { | ||||||||||||
| 987 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, | ||||||||||||
| 988 | Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, | ||||||||||||
| 989 | DWARFAddressSpace, Flags, ExtraData, Annotations.get(), | ||||||||||||
| 990 | Storage, ShouldCreate); | ||||||||||||
| 991 | } | ||||||||||||
| 992 | static DIDerivedType * | ||||||||||||
| 993 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||||||||||
| 994 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||||||||||
| 995 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 996 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
| 997 | Metadata *ExtraData, Metadata *Annotations, StorageType Storage, | ||||||||||||
| 998 | bool ShouldCreate = true); | ||||||||||||
| 999 | |||||||||||||
| 1000 | TempDIDerivedType cloneImpl() const { | ||||||||||||
| 1001 | return getTemporary( | ||||||||||||
| 1002 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||||||||||
| 1003 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||||||||||
| 1004 | getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); | ||||||||||||
| 1005 | } | ||||||||||||
| 1006 | |||||||||||||
| 1007 | public: | ||||||||||||
| 1008 | DEFINE_MDNODE_GET( | ||||||||||||
| 1009 | DIDerivedType, | ||||||||||||
| 1010 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
| 1011 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||||||||||
| 1012 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 1013 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
| 1014 | Metadata *ExtraData = nullptr, Metadata *Annotations = nullptr), | ||||||||||||
| 1015 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
| 1016 | OffsetInBits, DWARFAddressSpace, Flags, ExtraData, Annotations)) | ||||||||||||
| 1017 | DEFINE_MDNODE_GET(DIDerivedType, | ||||||||||||
| 1018 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
| 1019 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
| 1020 | uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 1021 | std::optional<unsigned> DWARFAddressSpace, DIFlags Flags, | ||||||||||||
| 1022 | Metadata *ExtraData = nullptr, | ||||||||||||
| 1023 | DINodeArray Annotations = nullptr), | ||||||||||||
| 1024 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, | ||||||||||||
| 1025 | AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, | ||||||||||||
| 1026 | ExtraData, Annotations)) | ||||||||||||
| 1027 | |||||||||||||
| 1028 | TempDIDerivedType clone() const { return cloneImpl(); } | ||||||||||||
| 1029 | |||||||||||||
| 1030 | /// Get the base type this is derived from. | ||||||||||||
| 1031 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||||||||||
| 1032 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||||||||||
| 1033 | |||||||||||||
| 1034 | /// \returns The DWARF address space of the memory pointed to or referenced by | ||||||||||||
| 1035 | /// a pointer or reference type respectively. | ||||||||||||
| 1036 | std::optional<unsigned> getDWARFAddressSpace() const { | ||||||||||||
| 1037 | return DWARFAddressSpace; | ||||||||||||
| 1038 | } | ||||||||||||
| 1039 | |||||||||||||
| 1040 | /// Get extra data associated with this derived type. | ||||||||||||
| 1041 | /// | ||||||||||||
| 1042 | /// Class type for pointer-to-members, objective-c property node for ivars, | ||||||||||||
| 1043 | /// global constant wrapper for static members, or virtual base pointer offset | ||||||||||||
| 1044 | /// for inheritance. | ||||||||||||
| 1045 | /// | ||||||||||||
| 1046 | /// TODO: Separate out types that need this extra operand: pointer-to-member | ||||||||||||
| 1047 | /// types and member fields (static members and ivars). | ||||||||||||
| 1048 | Metadata *getExtraData() const { return getRawExtraData(); } | ||||||||||||
| 1049 | Metadata *getRawExtraData() const { return getOperand(4); } | ||||||||||||
| 1050 | |||||||||||||
| 1051 | /// Get annotations associated with this derived type. | ||||||||||||
| 1052 | DINodeArray getAnnotations() const { | ||||||||||||
| 1053 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
| 1054 | } | ||||||||||||
| 1055 | Metadata *getRawAnnotations() const { return getOperand(5); } | ||||||||||||
| 1056 | |||||||||||||
| 1057 | /// Get casted version of extra data. | ||||||||||||
| 1058 | /// @{ | ||||||||||||
| 1059 | DIType *getClassType() const; | ||||||||||||
| 1060 | |||||||||||||
| 1061 | DIObjCProperty *getObjCProperty() const { | ||||||||||||
| 1062 | return dyn_cast_or_null<DIObjCProperty>(getExtraData()); | ||||||||||||
| 1063 | } | ||||||||||||
| 1064 | |||||||||||||
| 1065 | uint32_t getVBPtrOffset() const; | ||||||||||||
| 1066 | |||||||||||||
| 1067 | Constant *getStorageOffsetInBits() const; | ||||||||||||
| 1068 | |||||||||||||
| 1069 | Constant *getConstant() const; | ||||||||||||
| 1070 | |||||||||||||
| 1071 | Constant *getDiscriminantValue() const; | ||||||||||||
| 1072 | /// @} | ||||||||||||
| 1073 | |||||||||||||
| 1074 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1075 | return MD->getMetadataID() == DIDerivedTypeKind; | ||||||||||||
| 1076 | } | ||||||||||||
| 1077 | }; | ||||||||||||
| 1078 | |||||||||||||
| 1079 | /// Composite types. | ||||||||||||
| 1080 | /// | ||||||||||||
| 1081 | /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). | ||||||||||||
| 1082 | /// TODO: Create a custom, unrelated node for DW_TAG_array_type. | ||||||||||||
| 1083 | class DICompositeType : public DIType { | ||||||||||||
| 1084 | friend class LLVMContextImpl; | ||||||||||||
| 1085 | friend class MDNode; | ||||||||||||
| 1086 | |||||||||||||
| 1087 | unsigned RuntimeLang; | ||||||||||||
| 1088 | |||||||||||||
| 1089 | DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
| 1090 | unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, | ||||||||||||
| 1091 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
| 1092 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 1093 | : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, | ||||||||||||
| 1094 | AlignInBits, OffsetInBits, Flags, Ops), | ||||||||||||
| 1095 | RuntimeLang(RuntimeLang) {} | ||||||||||||
| 1096 | ~DICompositeType() = default; | ||||||||||||
| 1097 | |||||||||||||
| 1098 | /// Change fields in place. | ||||||||||||
| 1099 | void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang, | ||||||||||||
| 1100 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 1101 | DIFlags Flags) { | ||||||||||||
| 1102 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1102, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 1103 | assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate")(static_cast <bool> (getRawIdentifier() && "Only ODR-uniqued nodes should mutate" ) ? void (0) : __assert_fail ("getRawIdentifier() && \"Only ODR-uniqued nodes should mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1103, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 1104 | this->RuntimeLang = RuntimeLang; | ||||||||||||
| 1105 | DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags); | ||||||||||||
| 1106 | } | ||||||||||||
| 1107 | |||||||||||||
| 1108 | static DICompositeType * | ||||||||||||
| 1109 | getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, | ||||||||||||
| 1110 | unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
| 1111 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
| 1112 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||||||||||
| 1113 | DITemplateParameterArray TemplateParams, StringRef Identifier, | ||||||||||||
| 1114 | DIDerivedType *Discriminator, Metadata *DataLocation, | ||||||||||||
| 1115 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||||||||||
| 1116 | DINodeArray Annotations, StorageType Storage, | ||||||||||||
| 1117 | bool ShouldCreate = true) { | ||||||||||||
| 1118 | return getImpl( | ||||||||||||
| 1119 | Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, | ||||||||||||
| 1120 | BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), | ||||||||||||
| 1121 | RuntimeLang, VTableHolder, TemplateParams.get(), | ||||||||||||
| 1122 | getCanonicalMDString(Context, Identifier), Discriminator, DataLocation, | ||||||||||||
| 1123 | Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate); | ||||||||||||
| 1124 | } | ||||||||||||
| 1125 | static DICompositeType * | ||||||||||||
| 1126 | getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, | ||||||||||||
| 1127 | unsigned Line, Metadata *Scope, Metadata *BaseType, | ||||||||||||
| 1128 | uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, | ||||||||||||
| 1129 | DIFlags Flags, Metadata *Elements, unsigned RuntimeLang, | ||||||||||||
| 1130 | Metadata *VTableHolder, Metadata *TemplateParams, | ||||||||||||
| 1131 | MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation, | ||||||||||||
| 1132 | Metadata *Associated, Metadata *Allocated, Metadata *Rank, | ||||||||||||
| 1133 | Metadata *Annotations, StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 1134 | |||||||||||||
| 1135 | TempDICompositeType cloneImpl() const { | ||||||||||||
| 1136 | return getTemporary( | ||||||||||||
| 1137 | getContext(), getTag(), getName(), getFile(), getLine(), getScope(), | ||||||||||||
| 1138 | getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), | ||||||||||||
| 1139 | getFlags(), getElements(), getRuntimeLang(), getVTableHolder(), | ||||||||||||
| 1140 | getTemplateParams(), getIdentifier(), getDiscriminator(), | ||||||||||||
| 1141 | getRawDataLocation(), getRawAssociated(), getRawAllocated(), | ||||||||||||
| 1142 | getRawRank(), getAnnotations()); | ||||||||||||
| 1143 | } | ||||||||||||
| 1144 | |||||||||||||
| 1145 | public: | ||||||||||||
| 1146 | DEFINE_MDNODE_GET( | ||||||||||||
| 1147 | DICompositeType, | ||||||||||||
| 1148 | (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
| 1149 | DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, | ||||||||||||
| 1150 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
| 1151 | DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder, | ||||||||||||
| 1152 | DITemplateParameterArray TemplateParams = nullptr, | ||||||||||||
| 1153 | StringRef Identifier = "", DIDerivedType *Discriminator = nullptr, | ||||||||||||
| 1154 | Metadata *DataLocation = nullptr, Metadata *Associated = nullptr, | ||||||||||||
| 1155 | Metadata *Allocated = nullptr, Metadata *Rank = nullptr, | ||||||||||||
| 1156 | DINodeArray Annotations = nullptr), | ||||||||||||
| 1157 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
| 1158 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||||||||||
| 1159 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||||||||||
| 1160 | Annotations)) | ||||||||||||
| 1161 | DEFINE_MDNODE_GET( | ||||||||||||
| 1162 | DICompositeType, | ||||||||||||
| 1163 | (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
| 1164 | Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, | ||||||||||||
| 1165 | uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags, | ||||||||||||
| 1166 | Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
| 1167 | Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr, | ||||||||||||
| 1168 | Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr, | ||||||||||||
| 1169 | Metadata *Associated = nullptr, Metadata *Allocated = nullptr, | ||||||||||||
| 1170 | Metadata *Rank = nullptr, Metadata *Annotations = nullptr), | ||||||||||||
| 1171 | (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, | ||||||||||||
| 1172 | OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, | ||||||||||||
| 1173 | Identifier, Discriminator, DataLocation, Associated, Allocated, Rank, | ||||||||||||
| 1174 | Annotations)) | ||||||||||||
| 1175 | |||||||||||||
| 1176 | TempDICompositeType clone() const { return cloneImpl(); } | ||||||||||||
| 1177 | |||||||||||||
| 1178 | /// Get a DICompositeType with the given ODR identifier. | ||||||||||||
| 1179 | /// | ||||||||||||
| 1180 | /// If \a LLVMContext::isODRUniquingDebugTypes(), gets the mapped | ||||||||||||
| 1181 | /// DICompositeType for the given ODR \c Identifier. If none exists, creates | ||||||||||||
| 1182 | /// a new node. | ||||||||||||
| 1183 | /// | ||||||||||||
| 1184 | /// Else, returns \c nullptr. | ||||||||||||
| 1185 | static DICompositeType * | ||||||||||||
| 1186 | getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||||||||||
| 1187 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||||||||||
| 1188 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 1189 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||||||||||
| 1190 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
| 1191 | Metadata *TemplateParams, Metadata *Discriminator, | ||||||||||||
| 1192 | Metadata *DataLocation, Metadata *Associated, Metadata *Allocated, | ||||||||||||
| 1193 | Metadata *Rank, Metadata *Annotations); | ||||||||||||
| 1194 | static DICompositeType *getODRTypeIfExists(LLVMContext &Context, | ||||||||||||
| 1195 | MDString &Identifier); | ||||||||||||
| 1196 | |||||||||||||
| 1197 | /// Build a DICompositeType with the given ODR identifier. | ||||||||||||
| 1198 | /// | ||||||||||||
| 1199 | /// Looks up the mapped DICompositeType for the given ODR \c Identifier. If | ||||||||||||
| 1200 | /// it doesn't exist, creates a new one. If it does exist and \a | ||||||||||||
| 1201 | /// isForwardDecl(), and the new arguments would be a definition, mutates the | ||||||||||||
| 1202 | /// the type in place. In either case, returns the type. | ||||||||||||
| 1203 | /// | ||||||||||||
| 1204 | /// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns | ||||||||||||
| 1205 | /// nullptr. | ||||||||||||
| 1206 | static DICompositeType * | ||||||||||||
| 1207 | buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag, | ||||||||||||
| 1208 | MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, | ||||||||||||
| 1209 | Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, | ||||||||||||
| 1210 | uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements, | ||||||||||||
| 1211 | unsigned RuntimeLang, Metadata *VTableHolder, | ||||||||||||
| 1212 | Metadata *TemplateParams, Metadata *Discriminator, | ||||||||||||
| 1213 | Metadata *DataLocation, Metadata *Associated, | ||||||||||||
| 1214 | Metadata *Allocated, Metadata *Rank, Metadata *Annotations); | ||||||||||||
| 1215 | |||||||||||||
| 1216 | DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); } | ||||||||||||
| 1217 | DINodeArray getElements() const { | ||||||||||||
| 1218 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
| 1219 | } | ||||||||||||
| 1220 | DIType *getVTableHolder() const { | ||||||||||||
| 1221 | return cast_or_null<DIType>(getRawVTableHolder()); | ||||||||||||
| 1222 | } | ||||||||||||
| 1223 | DITemplateParameterArray getTemplateParams() const { | ||||||||||||
| 1224 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||||||||||
| 1225 | } | ||||||||||||
| 1226 | StringRef getIdentifier() const { return getStringOperand(7); } | ||||||||||||
| 1227 | unsigned getRuntimeLang() const { return RuntimeLang; } | ||||||||||||
| 1228 | |||||||||||||
| 1229 | Metadata *getRawBaseType() const { return getOperand(3); } | ||||||||||||
| 1230 | Metadata *getRawElements() const { return getOperand(4); } | ||||||||||||
| 1231 | Metadata *getRawVTableHolder() const { return getOperand(5); } | ||||||||||||
| 1232 | Metadata *getRawTemplateParams() const { return getOperand(6); } | ||||||||||||
| 1233 | MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } | ||||||||||||
| 1234 | Metadata *getRawDiscriminator() const { return getOperand(8); } | ||||||||||||
| 1235 | DIDerivedType *getDiscriminator() const { | ||||||||||||
| 1236 | return getOperandAs<DIDerivedType>(8); | ||||||||||||
| 1237 | } | ||||||||||||
| 1238 | Metadata *getRawDataLocation() const { return getOperand(9); } | ||||||||||||
| 1239 | DIVariable *getDataLocation() const { | ||||||||||||
| 1240 | return dyn_cast_or_null<DIVariable>(getRawDataLocation()); | ||||||||||||
| 1241 | } | ||||||||||||
| 1242 | DIExpression *getDataLocationExp() const { | ||||||||||||
| 1243 | return dyn_cast_or_null<DIExpression>(getRawDataLocation()); | ||||||||||||
| 1244 | } | ||||||||||||
| 1245 | Metadata *getRawAssociated() const { return getOperand(10); } | ||||||||||||
| 1246 | DIVariable *getAssociated() const { | ||||||||||||
| 1247 | return dyn_cast_or_null<DIVariable>(getRawAssociated()); | ||||||||||||
| 1248 | } | ||||||||||||
| 1249 | DIExpression *getAssociatedExp() const { | ||||||||||||
| 1250 | return dyn_cast_or_null<DIExpression>(getRawAssociated()); | ||||||||||||
| 1251 | } | ||||||||||||
| 1252 | Metadata *getRawAllocated() const { return getOperand(11); } | ||||||||||||
| 1253 | DIVariable *getAllocated() const { | ||||||||||||
| 1254 | return dyn_cast_or_null<DIVariable>(getRawAllocated()); | ||||||||||||
| 1255 | } | ||||||||||||
| 1256 | DIExpression *getAllocatedExp() const { | ||||||||||||
| 1257 | return dyn_cast_or_null<DIExpression>(getRawAllocated()); | ||||||||||||
| 1258 | } | ||||||||||||
| 1259 | Metadata *getRawRank() const { return getOperand(12); } | ||||||||||||
| 1260 | ConstantInt *getRankConst() const { | ||||||||||||
| 1261 | if (auto *MD = dyn_cast_or_null<ConstantAsMetadata>(getRawRank())) | ||||||||||||
| 1262 | return dyn_cast_or_null<ConstantInt>(MD->getValue()); | ||||||||||||
| 1263 | return nullptr; | ||||||||||||
| 1264 | } | ||||||||||||
| 1265 | DIExpression *getRankExp() const { | ||||||||||||
| 1266 | return dyn_cast_or_null<DIExpression>(getRawRank()); | ||||||||||||
| 1267 | } | ||||||||||||
| 1268 | |||||||||||||
| 1269 | Metadata *getRawAnnotations() const { return getOperand(13); } | ||||||||||||
| 1270 | DINodeArray getAnnotations() const { | ||||||||||||
| 1271 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
| 1272 | } | ||||||||||||
| 1273 | |||||||||||||
| 1274 | /// Replace operands. | ||||||||||||
| 1275 | /// | ||||||||||||
| 1276 | /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision | ||||||||||||
| 1277 | /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track | ||||||||||||
| 1278 | /// of its movement if necessary. | ||||||||||||
| 1279 | /// @{ | ||||||||||||
| 1280 | void replaceElements(DINodeArray Elements) { | ||||||||||||
| 1281 | #ifndef NDEBUG | ||||||||||||
| 1282 | for (DINode *Op : getElements()) | ||||||||||||
| 1283 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1284, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
| 1284 | "Lost a member during member list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a member during member list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a member during member list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1284, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 1285 | #endif | ||||||||||||
| 1286 | replaceOperandWith(4, Elements.get()); | ||||||||||||
| 1287 | } | ||||||||||||
| 1288 | |||||||||||||
| 1289 | void replaceVTableHolder(DIType *VTableHolder) { | ||||||||||||
| 1290 | replaceOperandWith(5, VTableHolder); | ||||||||||||
| 1291 | } | ||||||||||||
| 1292 | |||||||||||||
| 1293 | void replaceTemplateParams(DITemplateParameterArray TemplateParams) { | ||||||||||||
| 1294 | replaceOperandWith(6, TemplateParams.get()); | ||||||||||||
| 1295 | } | ||||||||||||
| 1296 | /// @} | ||||||||||||
| 1297 | |||||||||||||
| 1298 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1299 | return MD->getMetadataID() == DICompositeTypeKind; | ||||||||||||
| 1300 | } | ||||||||||||
| 1301 | }; | ||||||||||||
| 1302 | |||||||||||||
| 1303 | /// Type array for a subprogram. | ||||||||||||
| 1304 | /// | ||||||||||||
| 1305 | /// TODO: Fold the array of types in directly as operands. | ||||||||||||
| 1306 | class DISubroutineType : public DIType { | ||||||||||||
| 1307 | friend class LLVMContextImpl; | ||||||||||||
| 1308 | friend class MDNode; | ||||||||||||
| 1309 | |||||||||||||
| 1310 | /// The calling convention used with DW_AT_calling_convention. Actually of | ||||||||||||
| 1311 | /// type dwarf::CallingConvention. | ||||||||||||
| 1312 | uint8_t CC; | ||||||||||||
| 1313 | |||||||||||||
| 1314 | DISubroutineType(LLVMContext &C, StorageType Storage, DIFlags Flags, | ||||||||||||
| 1315 | uint8_t CC, ArrayRef<Metadata *> Ops); | ||||||||||||
| 1316 | ~DISubroutineType() = default; | ||||||||||||
| 1317 | |||||||||||||
| 1318 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||||||||||
| 1319 | uint8_t CC, DITypeRefArray TypeArray, | ||||||||||||
| 1320 | StorageType Storage, | ||||||||||||
| 1321 | bool ShouldCreate = true) { | ||||||||||||
| 1322 | return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate); | ||||||||||||
| 1323 | } | ||||||||||||
| 1324 | static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags, | ||||||||||||
| 1325 | uint8_t CC, Metadata *TypeArray, | ||||||||||||
| 1326 | StorageType Storage, | ||||||||||||
| 1327 | bool ShouldCreate = true); | ||||||||||||
| 1328 | |||||||||||||
| 1329 | TempDISubroutineType cloneImpl() const { | ||||||||||||
| 1330 | return getTemporary(getContext(), getFlags(), getCC(), getTypeArray()); | ||||||||||||
| 1331 | } | ||||||||||||
| 1332 | |||||||||||||
| 1333 | public: | ||||||||||||
| 1334 | DEFINE_MDNODE_GET(DISubroutineType, | ||||||||||||
| 1335 | (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray), | ||||||||||||
| 1336 | (Flags, CC, TypeArray)) | ||||||||||||
| 1337 | DEFINE_MDNODE_GET(DISubroutineType, | ||||||||||||
| 1338 | (DIFlags Flags, uint8_t CC, Metadata *TypeArray), | ||||||||||||
| 1339 | (Flags, CC, TypeArray)) | ||||||||||||
| 1340 | |||||||||||||
| 1341 | TempDISubroutineType clone() const { return cloneImpl(); } | ||||||||||||
| 1342 | // Returns a new temporary DISubroutineType with updated CC | ||||||||||||
| 1343 | TempDISubroutineType cloneWithCC(uint8_t CC) const { | ||||||||||||
| 1344 | auto NewTy = clone(); | ||||||||||||
| 1345 | NewTy->CC = CC; | ||||||||||||
| 1346 | return NewTy; | ||||||||||||
| 1347 | } | ||||||||||||
| 1348 | |||||||||||||
| 1349 | uint8_t getCC() const { return CC; } | ||||||||||||
| 1350 | |||||||||||||
| 1351 | DITypeRefArray getTypeArray() const { | ||||||||||||
| 1352 | return cast_or_null<MDTuple>(getRawTypeArray()); | ||||||||||||
| 1353 | } | ||||||||||||
| 1354 | |||||||||||||
| 1355 | Metadata *getRawTypeArray() const { return getOperand(3); } | ||||||||||||
| 1356 | |||||||||||||
| 1357 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1358 | return MD->getMetadataID() == DISubroutineTypeKind; | ||||||||||||
| 1359 | } | ||||||||||||
| 1360 | }; | ||||||||||||
| 1361 | |||||||||||||
| 1362 | /// Compile unit. | ||||||||||||
| 1363 | class DICompileUnit : public DIScope { | ||||||||||||
| 1364 | friend class LLVMContextImpl; | ||||||||||||
| 1365 | friend class MDNode; | ||||||||||||
| 1366 | |||||||||||||
| 1367 | public: | ||||||||||||
| 1368 | enum DebugEmissionKind : unsigned { | ||||||||||||
| 1369 | NoDebug = 0, | ||||||||||||
| 1370 | FullDebug, | ||||||||||||
| 1371 | LineTablesOnly, | ||||||||||||
| 1372 | DebugDirectivesOnly, | ||||||||||||
| 1373 | LastEmissionKind = DebugDirectivesOnly | ||||||||||||
| 1374 | }; | ||||||||||||
| 1375 | |||||||||||||
| 1376 | enum class DebugNameTableKind : unsigned { | ||||||||||||
| 1377 | Default = 0, | ||||||||||||
| 1378 | GNU = 1, | ||||||||||||
| 1379 | None = 2, | ||||||||||||
| 1380 | LastDebugNameTableKind = None | ||||||||||||
| 1381 | }; | ||||||||||||
| 1382 | |||||||||||||
| 1383 | static std::optional<DebugEmissionKind> getEmissionKind(StringRef Str); | ||||||||||||
| 1384 | static const char *emissionKindString(DebugEmissionKind EK); | ||||||||||||
| 1385 | static std::optional<DebugNameTableKind> getNameTableKind(StringRef Str); | ||||||||||||
| 1386 | static const char *nameTableKindString(DebugNameTableKind PK); | ||||||||||||
| 1387 | |||||||||||||
| 1388 | private: | ||||||||||||
| 1389 | unsigned SourceLanguage; | ||||||||||||
| 1390 | bool IsOptimized; | ||||||||||||
| 1391 | unsigned RuntimeVersion; | ||||||||||||
| 1392 | unsigned EmissionKind; | ||||||||||||
| 1393 | uint64_t DWOId; | ||||||||||||
| 1394 | bool SplitDebugInlining; | ||||||||||||
| 1395 | bool DebugInfoForProfiling; | ||||||||||||
| 1396 | unsigned NameTableKind; | ||||||||||||
| 1397 | bool RangesBaseAddress; | ||||||||||||
| 1398 | |||||||||||||
| 1399 | DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, | ||||||||||||
| 1400 | bool IsOptimized, unsigned RuntimeVersion, | ||||||||||||
| 1401 | unsigned EmissionKind, uint64_t DWOId, bool SplitDebugInlining, | ||||||||||||
| 1402 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||||||||||
| 1403 | bool RangesBaseAddress, ArrayRef<Metadata *> Ops); | ||||||||||||
| 1404 | ~DICompileUnit() = default; | ||||||||||||
| 1405 | |||||||||||||
| 1406 | static DICompileUnit * | ||||||||||||
| 1407 | getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, | ||||||||||||
| 1408 | StringRef Producer, bool IsOptimized, StringRef Flags, | ||||||||||||
| 1409 | unsigned RuntimeVersion, StringRef SplitDebugFilename, | ||||||||||||
| 1410 | unsigned EmissionKind, DICompositeTypeArray EnumTypes, | ||||||||||||
| 1411 | DIScopeArray RetainedTypes, | ||||||||||||
| 1412 | DIGlobalVariableExpressionArray GlobalVariables, | ||||||||||||
| 1413 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, | ||||||||||||
| 1414 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, | ||||||||||||
| 1415 | unsigned NameTableKind, bool RangesBaseAddress, StringRef SysRoot, | ||||||||||||
| 1416 | StringRef SDK, StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 1417 | return getImpl( | ||||||||||||
| 1418 | Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), | ||||||||||||
| 1419 | IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, | ||||||||||||
| 1420 | getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, | ||||||||||||
| 1421 | EnumTypes.get(), RetainedTypes.get(), GlobalVariables.get(), | ||||||||||||
| 1422 | ImportedEntities.get(), Macros.get(), DWOId, SplitDebugInlining, | ||||||||||||
| 1423 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, | ||||||||||||
| 1424 | getCanonicalMDString(Context, SysRoot), | ||||||||||||
| 1425 | getCanonicalMDString(Context, SDK), Storage, ShouldCreate); | ||||||||||||
| 1426 | } | ||||||||||||
| 1427 | static DICompileUnit * | ||||||||||||
| 1428 | getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, | ||||||||||||
| 1429 | MDString *Producer, bool IsOptimized, MDString *Flags, | ||||||||||||
| 1430 | unsigned RuntimeVersion, MDString *SplitDebugFilename, | ||||||||||||
| 1431 | unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, | ||||||||||||
| 1432 | Metadata *GlobalVariables, Metadata *ImportedEntities, | ||||||||||||
| 1433 | Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, | ||||||||||||
| 1434 | bool DebugInfoForProfiling, unsigned NameTableKind, | ||||||||||||
| 1435 | bool RangesBaseAddress, MDString *SysRoot, MDString *SDK, | ||||||||||||
| 1436 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 1437 | |||||||||||||
| 1438 | TempDICompileUnit cloneImpl() const { | ||||||||||||
| 1439 | return getTemporary( | ||||||||||||
| 1440 | getContext(), getSourceLanguage(), getFile(), getProducer(), | ||||||||||||
| 1441 | isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), | ||||||||||||
| 1442 | getEmissionKind(), getEnumTypes(), getRetainedTypes(), | ||||||||||||
| 1443 | getGlobalVariables(), getImportedEntities(), getMacros(), DWOId, | ||||||||||||
| 1444 | getSplitDebugInlining(), getDebugInfoForProfiling(), getNameTableKind(), | ||||||||||||
| 1445 | getRangesBaseAddress(), getSysRoot(), getSDK()); | ||||||||||||
| 1446 | } | ||||||||||||
| 1447 | |||||||||||||
| 1448 | public: | ||||||||||||
| 1449 | static void get() = delete; | ||||||||||||
| 1450 | static void getIfExists() = delete; | ||||||||||||
| 1451 | |||||||||||||
| 1452 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1453 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1454 | (unsigned SourceLanguage, DIFile *File, StringRef Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1455 | bool IsOptimized, StringRef Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1456 | StringRef SplitDebugFilename, DebugEmissionKind EmissionKind,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1457 | DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1458 | DIGlobalVariableExpressionArray GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1459 | DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1460 | uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1461 | DebugNameTableKind NameTableKind, bool RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1462 | StringRef SysRoot, StringRef SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1463 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1464 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1465 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1466 | DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1467 | SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes, DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK ((SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, (unsigned)NameTableKind, RangesBaseAddress , SysRoot, SDK)), Distinct); } static TempDICompileUnit getTemporary (LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized , StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename , DebugEmissionKind EmissionKind, DICompositeTypeArray EnumTypes , DIScopeArray RetainedTypes, DIGlobalVariableExpressionArray GlobalVariables, DIImportedEntityArray ImportedEntities, DIMacroNodeArray Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , DebugNameTableKind NameTableKind, bool RangesBaseAddress, StringRef SysRoot, StringRef SDK))) { return TempDICompileUnit( getImpl (Context, DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer , IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind , EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities , Macros, DWOId, SplitDebugInlining, DebugInfoForProfiling, ( unsigned)NameTableKind, RangesBaseAddress, SysRoot, SDK)), Temporary )); } | ||||||||||||
| 1468 | DEFINE_MDNODE_GET_DISTINCT_TEMPORARY(static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1469 | DICompileUnit,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1470 | (unsigned SourceLanguage, Metadata *File, MDString *Producer,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1471 | bool IsOptimized, MDString *Flags, unsigned RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1472 | MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1473 | Metadata *RetainedTypes, Metadata *GlobalVariables,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1474 | Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1475 | bool SplitDebugInlining, bool DebugInfoForProfiling,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1476 | unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1477 | MDString *SDK),static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1478 | (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1479 | SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1480 | GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining,static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1481 | DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot, SDK))static DICompileUnit *getDistinct(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK ((unsigned SourceLanguage, Metadata *File, MDString *Producer , bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *GlobalVariables , Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId , bool SplitDebugInlining, bool DebugInfoForProfiling, unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot, MDString *SDK))) { return getImpl(Context, DEFINE_MDNODE_GET_UNPACK(( SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion , SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId, SplitDebugInlining , DebugInfoForProfiling, NameTableKind, RangesBaseAddress, SysRoot , SDK)), Distinct); } static TempDICompileUnit getTemporary(LLVMContext &Context, DEFINE_MDNODE_GET_UNPACK((unsigned SourceLanguage , Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename , unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes , Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros, uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling , unsigned NameTableKind, bool RangesBaseAddress, MDString *SysRoot , MDString *SDK))) { return TempDICompileUnit( getImpl(Context , DEFINE_MDNODE_GET_UNPACK((SourceLanguage, File, Producer, IsOptimized , Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes , RetainedTypes, GlobalVariables, ImportedEntities, Macros, DWOId , SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress , SysRoot, SDK)), Temporary)); } | ||||||||||||
| 1482 | |||||||||||||
| 1483 | TempDICompileUnit clone() const { return cloneImpl(); } | ||||||||||||
| 1484 | |||||||||||||
| 1485 | unsigned getSourceLanguage() const { return SourceLanguage; } | ||||||||||||
| 1486 | bool isOptimized() const { return IsOptimized; } | ||||||||||||
| 1487 | unsigned getRuntimeVersion() const { return RuntimeVersion; } | ||||||||||||
| 1488 | DebugEmissionKind getEmissionKind() const { | ||||||||||||
| 1489 | return (DebugEmissionKind)EmissionKind; | ||||||||||||
| 1490 | } | ||||||||||||
| 1491 | bool isDebugDirectivesOnly() const { | ||||||||||||
| 1492 | return EmissionKind == DebugDirectivesOnly; | ||||||||||||
| 1493 | } | ||||||||||||
| 1494 | bool getDebugInfoForProfiling() const { return DebugInfoForProfiling; } | ||||||||||||
| 1495 | DebugNameTableKind getNameTableKind() const { | ||||||||||||
| 1496 | return (DebugNameTableKind)NameTableKind; | ||||||||||||
| 1497 | } | ||||||||||||
| 1498 | bool getRangesBaseAddress() const { return RangesBaseAddress; } | ||||||||||||
| 1499 | StringRef getProducer() const { return getStringOperand(1); } | ||||||||||||
| 1500 | StringRef getFlags() const { return getStringOperand(2); } | ||||||||||||
| 1501 | StringRef getSplitDebugFilename() const { return getStringOperand(3); } | ||||||||||||
| 1502 | DICompositeTypeArray getEnumTypes() const { | ||||||||||||
| 1503 | return cast_or_null<MDTuple>(getRawEnumTypes()); | ||||||||||||
| 1504 | } | ||||||||||||
| 1505 | DIScopeArray getRetainedTypes() const { | ||||||||||||
| 1506 | return cast_or_null<MDTuple>(getRawRetainedTypes()); | ||||||||||||
| 1507 | } | ||||||||||||
| 1508 | DIGlobalVariableExpressionArray getGlobalVariables() const { | ||||||||||||
| 1509 | return cast_or_null<MDTuple>(getRawGlobalVariables()); | ||||||||||||
| 1510 | } | ||||||||||||
| 1511 | DIImportedEntityArray getImportedEntities() const { | ||||||||||||
| 1512 | return cast_or_null<MDTuple>(getRawImportedEntities()); | ||||||||||||
| 1513 | } | ||||||||||||
| 1514 | DIMacroNodeArray getMacros() const { | ||||||||||||
| 1515 | return cast_or_null<MDTuple>(getRawMacros()); | ||||||||||||
| 1516 | } | ||||||||||||
| 1517 | uint64_t getDWOId() const { return DWOId; } | ||||||||||||
| 1518 | void setDWOId(uint64_t DwoId) { DWOId = DwoId; } | ||||||||||||
| 1519 | bool getSplitDebugInlining() const { return SplitDebugInlining; } | ||||||||||||
| 1520 | void setSplitDebugInlining(bool SplitDebugInlining) { | ||||||||||||
| 1521 | this->SplitDebugInlining = SplitDebugInlining; | ||||||||||||
| 1522 | } | ||||||||||||
| 1523 | StringRef getSysRoot() const { return getStringOperand(9); } | ||||||||||||
| 1524 | StringRef getSDK() const { return getStringOperand(10); } | ||||||||||||
| 1525 | |||||||||||||
| 1526 | MDString *getRawProducer() const { return getOperandAs<MDString>(1); } | ||||||||||||
| 1527 | MDString *getRawFlags() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 1528 | MDString *getRawSplitDebugFilename() const { | ||||||||||||
| 1529 | return getOperandAs<MDString>(3); | ||||||||||||
| 1530 | } | ||||||||||||
| 1531 | Metadata *getRawEnumTypes() const { return getOperand(4); } | ||||||||||||
| 1532 | Metadata *getRawRetainedTypes() const { return getOperand(5); } | ||||||||||||
| 1533 | Metadata *getRawGlobalVariables() const { return getOperand(6); } | ||||||||||||
| 1534 | Metadata *getRawImportedEntities() const { return getOperand(7); } | ||||||||||||
| 1535 | Metadata *getRawMacros() const { return getOperand(8); } | ||||||||||||
| 1536 | MDString *getRawSysRoot() const { return getOperandAs<MDString>(9); } | ||||||||||||
| 1537 | MDString *getRawSDK() const { return getOperandAs<MDString>(10); } | ||||||||||||
| 1538 | |||||||||||||
| 1539 | /// Replace arrays. | ||||||||||||
| 1540 | /// | ||||||||||||
| 1541 | /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and | ||||||||||||
| 1542 | /// deleted on a uniquing collision. In practice, uniquing collisions on \a | ||||||||||||
| 1543 | /// DICompileUnit should be fairly rare. | ||||||||||||
| 1544 | /// @{ | ||||||||||||
| 1545 | void replaceEnumTypes(DICompositeTypeArray N) { | ||||||||||||
| 1546 | replaceOperandWith(4, N.get()); | ||||||||||||
| 1547 | } | ||||||||||||
| 1548 | void replaceRetainedTypes(DITypeArray N) { replaceOperandWith(5, N.get()); } | ||||||||||||
| 1549 | void replaceGlobalVariables(DIGlobalVariableExpressionArray N) { | ||||||||||||
| 1550 | replaceOperandWith(6, N.get()); | ||||||||||||
| 1551 | } | ||||||||||||
| 1552 | void replaceImportedEntities(DIImportedEntityArray N) { | ||||||||||||
| 1553 | replaceOperandWith(7, N.get()); | ||||||||||||
| 1554 | } | ||||||||||||
| 1555 | void replaceMacros(DIMacroNodeArray N) { replaceOperandWith(8, N.get()); } | ||||||||||||
| 1556 | /// @} | ||||||||||||
| 1557 | |||||||||||||
| 1558 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1559 | return MD->getMetadataID() == DICompileUnitKind; | ||||||||||||
| 1560 | } | ||||||||||||
| 1561 | }; | ||||||||||||
| 1562 | |||||||||||||
| 1563 | /// A scope for locals. | ||||||||||||
| 1564 | /// | ||||||||||||
| 1565 | /// A legal scope for lexical blocks, local variables, and debug info | ||||||||||||
| 1566 | /// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a | ||||||||||||
| 1567 | /// DILexicalBlockFile. | ||||||||||||
| 1568 | class DILocalScope : public DIScope { | ||||||||||||
| 1569 | protected: | ||||||||||||
| 1570 | DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, | ||||||||||||
| 1571 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 1572 | : DIScope(C, ID, Storage, Tag, Ops) {} | ||||||||||||
| 1573 | ~DILocalScope() = default; | ||||||||||||
| 1574 | |||||||||||||
| 1575 | public: | ||||||||||||
| 1576 | /// Get the subprogram for this scope. | ||||||||||||
| 1577 | /// | ||||||||||||
| 1578 | /// Return this if it's an \a DISubprogram; otherwise, look up the scope | ||||||||||||
| 1579 | /// chain. | ||||||||||||
| 1580 | DISubprogram *getSubprogram() const; | ||||||||||||
| 1581 | |||||||||||||
| 1582 | /// Traverses the scope chain rooted at RootScope until it hits a Subprogram, | ||||||||||||
| 1583 | /// recreating the chain with "NewSP" instead. | ||||||||||||
| 1584 | static DILocalScope * | ||||||||||||
| 1585 | cloneScopeForSubprogram(DILocalScope &RootScope, DISubprogram &NewSP, | ||||||||||||
| 1586 | LLVMContext &Ctx, | ||||||||||||
| 1587 | DenseMap<const MDNode *, MDNode *> &Cache); | ||||||||||||
| 1588 | |||||||||||||
| 1589 | /// Get the first non DILexicalBlockFile scope of this scope. | ||||||||||||
| 1590 | /// | ||||||||||||
| 1591 | /// Return this if it's not a \a DILexicalBlockFIle; otherwise, look up the | ||||||||||||
| 1592 | /// scope chain. | ||||||||||||
| 1593 | DILocalScope *getNonLexicalBlockFileScope() const; | ||||||||||||
| 1594 | |||||||||||||
| 1595 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1596 | return MD->getMetadataID() == DISubprogramKind || | ||||||||||||
| 1597 | MD->getMetadataID() == DILexicalBlockKind || | ||||||||||||
| 1598 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
| 1599 | } | ||||||||||||
| 1600 | }; | ||||||||||||
| 1601 | |||||||||||||
| 1602 | /// Subprogram description. | ||||||||||||
| 1603 | class DISubprogram : public DILocalScope { | ||||||||||||
| 1604 | friend class LLVMContextImpl; | ||||||||||||
| 1605 | friend class MDNode; | ||||||||||||
| 1606 | |||||||||||||
| 1607 | unsigned Line; | ||||||||||||
| 1608 | unsigned ScopeLine; | ||||||||||||
| 1609 | unsigned VirtualIndex; | ||||||||||||
| 1610 | |||||||||||||
| 1611 | /// In the MS ABI, the implicit 'this' parameter is adjusted in the prologue | ||||||||||||
| 1612 | /// of method overrides from secondary bases by this amount. It may be | ||||||||||||
| 1613 | /// negative. | ||||||||||||
| 1614 | int ThisAdjustment; | ||||||||||||
| 1615 | |||||||||||||
| 1616 | public: | ||||||||||||
| 1617 | /// Debug info subprogram flags. | ||||||||||||
| 1618 | enum DISPFlags : uint32_t { | ||||||||||||
| 1619 | #define HANDLE_DISP_FLAG(ID, NAME) SPFlag##NAME = ID, | ||||||||||||
| 1620 | #define DISP_FLAG_LARGEST_NEEDED | ||||||||||||
| 1621 | #include "llvm/IR/DebugInfoFlags.def" | ||||||||||||
| 1622 | SPFlagNonvirtual = SPFlagZero, | ||||||||||||
| 1623 | SPFlagVirtuality = SPFlagVirtual | SPFlagPureVirtual, | ||||||||||||
| 1624 | LLVM_MARK_AS_BITMASK_ENUM(SPFlagLargest)LLVM_BITMASK_LARGEST_ENUMERATOR = SPFlagLargest | ||||||||||||
| 1625 | }; | ||||||||||||
| 1626 | |||||||||||||
| 1627 | static DISPFlags getFlag(StringRef Flag); | ||||||||||||
| 1628 | static StringRef getFlagString(DISPFlags Flag); | ||||||||||||
| 1629 | |||||||||||||
| 1630 | /// Split up a flags bitfield for easier printing. | ||||||||||||
| 1631 | /// | ||||||||||||
| 1632 | /// Split \c Flags into \c SplitFlags, a vector of its components. Returns | ||||||||||||
| 1633 | /// any remaining (unrecognized) bits. | ||||||||||||
| 1634 | static DISPFlags splitFlags(DISPFlags Flags, | ||||||||||||
| 1635 | SmallVectorImpl<DISPFlags> &SplitFlags); | ||||||||||||
| 1636 | |||||||||||||
| 1637 | // Helper for converting old bitfields to new flags word. | ||||||||||||
| 1638 | static DISPFlags toSPFlags(bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
| 1639 | bool IsOptimized, | ||||||||||||
| 1640 | unsigned Virtuality = SPFlagNonvirtual, | ||||||||||||
| 1641 | bool IsMainSubprogram = false); | ||||||||||||
| 1642 | |||||||||||||
| 1643 | private: | ||||||||||||
| 1644 | DIFlags Flags; | ||||||||||||
| 1645 | DISPFlags SPFlags; | ||||||||||||
| 1646 | |||||||||||||
| 1647 | DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 1648 | unsigned ScopeLine, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
| 1649 | DIFlags Flags, DISPFlags SPFlags, ArrayRef<Metadata *> Ops); | ||||||||||||
| 1650 | ~DISubprogram() = default; | ||||||||||||
| 1651 | |||||||||||||
| 1652 | static DISubprogram * | ||||||||||||
| 1653 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
| 1654 | StringRef LinkageName, DIFile *File, unsigned Line, | ||||||||||||
| 1655 | DISubroutineType *Type, unsigned ScopeLine, DIType *ContainingType, | ||||||||||||
| 1656 | unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, | ||||||||||||
| 1657 | DISPFlags SPFlags, DICompileUnit *Unit, | ||||||||||||
| 1658 | DITemplateParameterArray TemplateParams, DISubprogram *Declaration, | ||||||||||||
| 1659 | DINodeArray RetainedNodes, DITypeArray ThrownTypes, | ||||||||||||
| 1660 | DINodeArray Annotations, StringRef TargetFuncName, | ||||||||||||
| 1661 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 1662 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
| 1663 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||||||||||
| 1664 | ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, | ||||||||||||
| 1665 | Flags, SPFlags, Unit, TemplateParams.get(), Declaration, | ||||||||||||
| 1666 | RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), | ||||||||||||
| 1667 | getCanonicalMDString(Context, TargetFuncName), | ||||||||||||
| 1668 | Storage, ShouldCreate); | ||||||||||||
| 1669 | } | ||||||||||||
| 1670 | static DISubprogram * | ||||||||||||
| 1671 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
| 1672 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||||||||||
| 1673 | unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, | ||||||||||||
| 1674 | int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||||||||||
| 1675 | Metadata *TemplateParams, Metadata *Declaration, | ||||||||||||
| 1676 | Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, | ||||||||||||
| 1677 | MDString *TargetFuncName, StorageType Storage, | ||||||||||||
| 1678 | bool ShouldCreate = true); | ||||||||||||
| 1679 | |||||||||||||
| 1680 | TempDISubprogram cloneImpl() const { | ||||||||||||
| 1681 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||||||||||
| 1682 | getFile(), getLine(), getType(), getScopeLine(), | ||||||||||||
| 1683 | getContainingType(), getVirtualIndex(), | ||||||||||||
| 1684 | getThisAdjustment(), getFlags(), getSPFlags(), | ||||||||||||
| 1685 | getUnit(), getTemplateParams(), getDeclaration(), | ||||||||||||
| 1686 | getRetainedNodes(), getThrownTypes(), getAnnotations(), | ||||||||||||
| 1687 | getTargetFuncName()); | ||||||||||||
| 1688 | } | ||||||||||||
| 1689 | |||||||||||||
| 1690 | public: | ||||||||||||
| 1691 | DEFINE_MDNODE_GET( | ||||||||||||
| 1692 | DISubprogram, | ||||||||||||
| 1693 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||||||||||
| 1694 | unsigned Line, DISubroutineType *Type, unsigned ScopeLine, | ||||||||||||
| 1695 | DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
| 1696 | DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, | ||||||||||||
| 1697 | DITemplateParameterArray TemplateParams = nullptr, | ||||||||||||
| 1698 | DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, | ||||||||||||
| 1699 | DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr, | ||||||||||||
| 1700 | StringRef TargetFuncName = ""), | ||||||||||||
| 1701 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||||||||||
| 1702 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||||||||||
| 1703 | Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) | ||||||||||||
| 1704 | |||||||||||||
| 1705 | DEFINE_MDNODE_GET( | ||||||||||||
| 1706 | DISubprogram, | ||||||||||||
| 1707 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||||||||||
| 1708 | unsigned Line, Metadata *Type, unsigned ScopeLine, | ||||||||||||
| 1709 | Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, | ||||||||||||
| 1710 | DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, | ||||||||||||
| 1711 | Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, | ||||||||||||
| 1712 | Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, | ||||||||||||
| 1713 | Metadata *Annotations = nullptr, MDString *TargetFuncName = nullptr), | ||||||||||||
| 1714 | (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, | ||||||||||||
| 1715 | VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, | ||||||||||||
| 1716 | Declaration, RetainedNodes, ThrownTypes, Annotations, TargetFuncName)) | ||||||||||||
| 1717 | |||||||||||||
| 1718 | TempDISubprogram clone() const { return cloneImpl(); } | ||||||||||||
| 1719 | |||||||||||||
| 1720 | /// Returns a new temporary DISubprogram with updated Flags | ||||||||||||
| 1721 | TempDISubprogram cloneWithFlags(DIFlags NewFlags) const { | ||||||||||||
| 1722 | auto NewSP = clone(); | ||||||||||||
| 1723 | NewSP->Flags = NewFlags; | ||||||||||||
| 1724 | return NewSP; | ||||||||||||
| 1725 | } | ||||||||||||
| 1726 | |||||||||||||
| 1727 | public: | ||||||||||||
| 1728 | unsigned getLine() const { return Line; } | ||||||||||||
| 1729 | unsigned getVirtuality() const { return getSPFlags() & SPFlagVirtuality; } | ||||||||||||
| 1730 | unsigned getVirtualIndex() const { return VirtualIndex; } | ||||||||||||
| 1731 | int getThisAdjustment() const { return ThisAdjustment; } | ||||||||||||
| 1732 | unsigned getScopeLine() const { return ScopeLine; } | ||||||||||||
| 1733 | void setScopeLine(unsigned L) { | ||||||||||||
| 1734 | assert(isDistinct())(static_cast <bool> (isDistinct()) ? void (0) : __assert_fail ("isDistinct()", "llvm/include/llvm/IR/DebugInfoMetadata.h", 1734, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 1735 | ScopeLine = L; | ||||||||||||
| 1736 | } | ||||||||||||
| 1737 | DIFlags getFlags() const { return Flags; } | ||||||||||||
| 1738 | DISPFlags getSPFlags() const { return SPFlags; } | ||||||||||||
| 1739 | bool isLocalToUnit() const { return getSPFlags() & SPFlagLocalToUnit; } | ||||||||||||
| 1740 | bool isDefinition() const { return getSPFlags() & SPFlagDefinition; } | ||||||||||||
| 1741 | bool isOptimized() const { return getSPFlags() & SPFlagOptimized; } | ||||||||||||
| 1742 | bool isMainSubprogram() const { return getSPFlags() & SPFlagMainSubprogram; } | ||||||||||||
| 1743 | |||||||||||||
| 1744 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
| 1745 | bool isPrivate() const { | ||||||||||||
| 1746 | return (getFlags() & FlagAccessibility) == FlagPrivate; | ||||||||||||
| 1747 | } | ||||||||||||
| 1748 | bool isProtected() const { | ||||||||||||
| 1749 | return (getFlags() & FlagAccessibility) == FlagProtected; | ||||||||||||
| 1750 | } | ||||||||||||
| 1751 | bool isPublic() const { | ||||||||||||
| 1752 | return (getFlags() & FlagAccessibility) == FlagPublic; | ||||||||||||
| 1753 | } | ||||||||||||
| 1754 | bool isExplicit() const { return getFlags() & FlagExplicit; } | ||||||||||||
| 1755 | bool isPrototyped() const { return getFlags() & FlagPrototyped; } | ||||||||||||
| 1756 | bool areAllCallsDescribed() const { | ||||||||||||
| 1757 | return getFlags() & FlagAllCallsDescribed; | ||||||||||||
| 1758 | } | ||||||||||||
| 1759 | bool isPure() const { return getSPFlags() & SPFlagPure; } | ||||||||||||
| 1760 | bool isElemental() const { return getSPFlags() & SPFlagElemental; } | ||||||||||||
| 1761 | bool isRecursive() const { return getSPFlags() & SPFlagRecursive; } | ||||||||||||
| 1762 | bool isObjCDirect() const { return getSPFlags() & SPFlagObjCDirect; } | ||||||||||||
| 1763 | |||||||||||||
| 1764 | /// Check if this is deleted member function. | ||||||||||||
| 1765 | /// | ||||||||||||
| 1766 | /// Return true if this subprogram is a C++11 special | ||||||||||||
| 1767 | /// member function declared deleted. | ||||||||||||
| 1768 | bool isDeleted() const { return getSPFlags() & SPFlagDeleted; } | ||||||||||||
| 1769 | |||||||||||||
| 1770 | /// Check if this is reference-qualified. | ||||||||||||
| 1771 | /// | ||||||||||||
| 1772 | /// Return true if this subprogram is a C++11 reference-qualified non-static | ||||||||||||
| 1773 | /// member function (void foo() &). | ||||||||||||
| 1774 | bool isLValueReference() const { return getFlags() & FlagLValueReference; } | ||||||||||||
| 1775 | |||||||||||||
| 1776 | /// Check if this is rvalue-reference-qualified. | ||||||||||||
| 1777 | /// | ||||||||||||
| 1778 | /// Return true if this subprogram is a C++11 rvalue-reference-qualified | ||||||||||||
| 1779 | /// non-static member function (void foo() &&). | ||||||||||||
| 1780 | bool isRValueReference() const { return getFlags() & FlagRValueReference; } | ||||||||||||
| 1781 | |||||||||||||
| 1782 | /// Check if this is marked as noreturn. | ||||||||||||
| 1783 | /// | ||||||||||||
| 1784 | /// Return true if this subprogram is C++11 noreturn or C11 _Noreturn | ||||||||||||
| 1785 | bool isNoReturn() const { return getFlags() & FlagNoReturn; } | ||||||||||||
| 1786 | |||||||||||||
| 1787 | // Check if this routine is a compiler-generated thunk. | ||||||||||||
| 1788 | // | ||||||||||||
| 1789 | // Returns true if this subprogram is a thunk generated by the compiler. | ||||||||||||
| 1790 | bool isThunk() const { return getFlags() & FlagThunk; } | ||||||||||||
| 1791 | |||||||||||||
| 1792 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 1793 | |||||||||||||
| 1794 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 1795 | StringRef getLinkageName() const { return getStringOperand(3); } | ||||||||||||
| 1796 | /// Only used by clients of CloneFunction, and only right after the cloning. | ||||||||||||
| 1797 | void replaceLinkageName(MDString *LN) { replaceOperandWith(3, LN); } | ||||||||||||
| 1798 | |||||||||||||
| 1799 | DISubroutineType *getType() const { | ||||||||||||
| 1800 | return cast_or_null<DISubroutineType>(getRawType()); | ||||||||||||
| 1801 | } | ||||||||||||
| 1802 | DIType *getContainingType() const { | ||||||||||||
| 1803 | return cast_or_null<DIType>(getRawContainingType()); | ||||||||||||
| 1804 | } | ||||||||||||
| 1805 | void replaceType(DISubroutineType *Ty) { | ||||||||||||
| 1806 | assert(isDistinct() && "Only distinct nodes can mutate")(static_cast <bool> (isDistinct() && "Only distinct nodes can mutate" ) ? void (0) : __assert_fail ("isDistinct() && \"Only distinct nodes can mutate\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 1806, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 1807 | replaceOperandWith(4, Ty); | ||||||||||||
| 1808 | } | ||||||||||||
| 1809 | |||||||||||||
| 1810 | DICompileUnit *getUnit() const { | ||||||||||||
| 1811 | return cast_or_null<DICompileUnit>(getRawUnit()); | ||||||||||||
| 1812 | } | ||||||||||||
| 1813 | void replaceUnit(DICompileUnit *CU) { replaceOperandWith(5, CU); } | ||||||||||||
| 1814 | DITemplateParameterArray getTemplateParams() const { | ||||||||||||
| 1815 | return cast_or_null<MDTuple>(getRawTemplateParams()); | ||||||||||||
| 1816 | } | ||||||||||||
| 1817 | DISubprogram *getDeclaration() const { | ||||||||||||
| 1818 | return cast_or_null<DISubprogram>(getRawDeclaration()); | ||||||||||||
| 1819 | } | ||||||||||||
| 1820 | DINodeArray getRetainedNodes() const { | ||||||||||||
| 1821 | return cast_or_null<MDTuple>(getRawRetainedNodes()); | ||||||||||||
| 1822 | } | ||||||||||||
| 1823 | DITypeArray getThrownTypes() const { | ||||||||||||
| 1824 | return cast_or_null<MDTuple>(getRawThrownTypes()); | ||||||||||||
| 1825 | } | ||||||||||||
| 1826 | DINodeArray getAnnotations() const { | ||||||||||||
| 1827 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
| 1828 | } | ||||||||||||
| 1829 | StringRef getTargetFuncName() const { | ||||||||||||
| 1830 | return (getRawTargetFuncName()) ? getStringOperand(12) : StringRef(); | ||||||||||||
| 1831 | } | ||||||||||||
| 1832 | |||||||||||||
| 1833 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
| 1834 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 1835 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(3); } | ||||||||||||
| 1836 | Metadata *getRawType() const { return getOperand(4); } | ||||||||||||
| 1837 | Metadata *getRawUnit() const { return getOperand(5); } | ||||||||||||
| 1838 | Metadata *getRawDeclaration() const { return getOperand(6); } | ||||||||||||
| 1839 | Metadata *getRawRetainedNodes() const { return getOperand(7); } | ||||||||||||
| 1840 | Metadata *getRawContainingType() const { | ||||||||||||
| 1841 | return getNumOperands() > 8 ? getOperandAs<Metadata>(8) : nullptr; | ||||||||||||
| 1842 | } | ||||||||||||
| 1843 | Metadata *getRawTemplateParams() const { | ||||||||||||
| 1844 | return getNumOperands() > 9 ? getOperandAs<Metadata>(9) : nullptr; | ||||||||||||
| 1845 | } | ||||||||||||
| 1846 | Metadata *getRawThrownTypes() const { | ||||||||||||
| 1847 | return getNumOperands() > 10 ? getOperandAs<Metadata>(10) : nullptr; | ||||||||||||
| 1848 | } | ||||||||||||
| 1849 | Metadata *getRawAnnotations() const { | ||||||||||||
| 1850 | return getNumOperands() > 11 ? getOperandAs<Metadata>(11) : nullptr; | ||||||||||||
| 1851 | } | ||||||||||||
| 1852 | MDString *getRawTargetFuncName() const { | ||||||||||||
| 1853 | return getNumOperands() > 12 ? getOperandAs<MDString>(12) : nullptr; | ||||||||||||
| 1854 | } | ||||||||||||
| 1855 | |||||||||||||
| 1856 | void replaceRawLinkageName(MDString *LinkageName) { | ||||||||||||
| 1857 | replaceOperandWith(3, LinkageName); | ||||||||||||
| 1858 | } | ||||||||||||
| 1859 | |||||||||||||
| 1860 | /// Check if this subprogram describes the given function. | ||||||||||||
| 1861 | /// | ||||||||||||
| 1862 | /// FIXME: Should this be looking through bitcasts? | ||||||||||||
| 1863 | bool describes(const Function *F) const; | ||||||||||||
| 1864 | |||||||||||||
| 1865 | static bool classof(const Metadata *MD) { | ||||||||||||
| 1866 | return MD->getMetadataID() == DISubprogramKind; | ||||||||||||
| 1867 | } | ||||||||||||
| 1868 | }; | ||||||||||||
| 1869 | |||||||||||||
| 1870 | /// Debug location. | ||||||||||||
| 1871 | /// | ||||||||||||
| 1872 | /// A debug location in source code, used for debug info and otherwise. | ||||||||||||
| 1873 | class DILocation : public MDNode { | ||||||||||||
| 1874 | friend class LLVMContextImpl; | ||||||||||||
| 1875 | friend class MDNode; | ||||||||||||
| 1876 | |||||||||||||
| 1877 | DILocation(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 1878 | unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode); | ||||||||||||
| 1879 | ~DILocation() { dropAllReferences(); } | ||||||||||||
| 1880 | |||||||||||||
| 1881 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||||||||||
| 1882 | unsigned Column, Metadata *Scope, | ||||||||||||
| 1883 | Metadata *InlinedAt, bool ImplicitCode, | ||||||||||||
| 1884 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 1885 | static DILocation *getImpl(LLVMContext &Context, unsigned Line, | ||||||||||||
| 1886 | unsigned Column, DILocalScope *Scope, | ||||||||||||
| 1887 | DILocation *InlinedAt, bool ImplicitCode, | ||||||||||||
| 1888 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 1889 | return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope), | ||||||||||||
| 1890 | static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage, | ||||||||||||
| 1891 | ShouldCreate); | ||||||||||||
| 1892 | } | ||||||||||||
| 1893 | |||||||||||||
| 1894 | TempDILocation cloneImpl() const { | ||||||||||||
| 1895 | // Get the raw scope/inlinedAt since it is possible to invoke this on | ||||||||||||
| 1896 | // a DILocation containing temporary metadata. | ||||||||||||
| 1897 | return getTemporary(getContext(), getLine(), getColumn(), getRawScope(), | ||||||||||||
| 1898 | getRawInlinedAt(), isImplicitCode()); | ||||||||||||
| 1899 | } | ||||||||||||
| 1900 | |||||||||||||
| 1901 | public: | ||||||||||||
| 1902 | // Disallow replacing operands. | ||||||||||||
| 1903 | void replaceOperandWith(unsigned I, Metadata *New) = delete; | ||||||||||||
| 1904 | |||||||||||||
| 1905 | DEFINE_MDNODE_GET(DILocation, | ||||||||||||
| 1906 | (unsigned Line, unsigned Column, Metadata *Scope, | ||||||||||||
| 1907 | Metadata *InlinedAt = nullptr, bool ImplicitCode = false), | ||||||||||||
| 1908 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||||||||||
| 1909 | DEFINE_MDNODE_GET(DILocation, | ||||||||||||
| 1910 | (unsigned Line, unsigned Column, DILocalScope *Scope, | ||||||||||||
| 1911 | DILocation *InlinedAt = nullptr, | ||||||||||||
| 1912 | bool ImplicitCode = false), | ||||||||||||
| 1913 | (Line, Column, Scope, InlinedAt, ImplicitCode)) | ||||||||||||
| 1914 | |||||||||||||
| 1915 | /// Return a (temporary) clone of this. | ||||||||||||
| 1916 | TempDILocation clone() const { return cloneImpl(); } | ||||||||||||
| 1917 | |||||||||||||
| 1918 | unsigned getLine() const { return SubclassData32; } | ||||||||||||
| 1919 | unsigned getColumn() const { return SubclassData16; } | ||||||||||||
| 1920 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||||||||||
| 1921 | |||||||||||||
| 1922 | /// Return the linkage name of Subprogram. If the linkage name is empty, | ||||||||||||
| 1923 | /// return scope name (the demangled name). | ||||||||||||
| 1924 | StringRef getSubprogramLinkageName() const { | ||||||||||||
| 1925 | DISubprogram *SP = getScope()->getSubprogram(); | ||||||||||||
| 1926 | if (!SP) | ||||||||||||
| 1927 | return ""; | ||||||||||||
| 1928 | auto Name = SP->getLinkageName(); | ||||||||||||
| 1929 | if (!Name.empty()) | ||||||||||||
| 1930 | return Name; | ||||||||||||
| 1931 | return SP->getName(); | ||||||||||||
| 1932 | } | ||||||||||||
| 1933 | |||||||||||||
| 1934 | DILocation *getInlinedAt() const { | ||||||||||||
| 1935 | return cast_or_null<DILocation>(getRawInlinedAt()); | ||||||||||||
| 1936 | } | ||||||||||||
| 1937 | |||||||||||||
| 1938 | /// Check if the location corresponds to an implicit code. | ||||||||||||
| 1939 | /// When the ImplicitCode flag is true, it means that the Instruction | ||||||||||||
| 1940 | /// with this DILocation has been added by the front-end but it hasn't been | ||||||||||||
| 1941 | /// written explicitly by the user (e.g. cleanup stuff in C++ put on a closing | ||||||||||||
| 1942 | /// bracket). It's useful for code coverage to not show a counter on "empty" | ||||||||||||
| 1943 | /// lines. | ||||||||||||
| 1944 | bool isImplicitCode() const { return SubclassData1; } | ||||||||||||
| 1945 | void setImplicitCode(bool ImplicitCode) { SubclassData1 = ImplicitCode; } | ||||||||||||
| 1946 | |||||||||||||
| 1947 | DIFile *getFile() const { return getScope()->getFile(); } | ||||||||||||
| 1948 | StringRef getFilename() const { return getScope()->getFilename(); } | ||||||||||||
| 1949 | StringRef getDirectory() const { return getScope()->getDirectory(); } | ||||||||||||
| 1950 | std::optional<StringRef> getSource() const { return getScope()->getSource(); } | ||||||||||||
| 1951 | |||||||||||||
| 1952 | /// Get the scope where this is inlined. | ||||||||||||
| 1953 | /// | ||||||||||||
| 1954 | /// Walk through \a getInlinedAt() and return \a getScope() from the deepest | ||||||||||||
| 1955 | /// location. | ||||||||||||
| 1956 | DILocalScope *getInlinedAtScope() const { | ||||||||||||
| 1957 | if (auto *IA
| ||||||||||||
| 1958 | return IA->getInlinedAtScope(); | ||||||||||||
| 1959 | return getScope(); | ||||||||||||
| 1960 | } | ||||||||||||
| 1961 | |||||||||||||
| 1962 | /// Get the DWARF discriminator. | ||||||||||||
| 1963 | /// | ||||||||||||
| 1964 | /// DWARF discriminators distinguish identical file locations between | ||||||||||||
| 1965 | /// instructions that are on different basic blocks. | ||||||||||||
| 1966 | /// | ||||||||||||
| 1967 | /// There are 3 components stored in discriminator, from lower bits: | ||||||||||||
| 1968 | /// | ||||||||||||
| 1969 | /// Base discriminator: assigned by AddDiscriminators pass to identify IRs | ||||||||||||
| 1970 | /// that are defined by the same source line, but | ||||||||||||
| 1971 | /// different basic blocks. | ||||||||||||
| 1972 | /// Duplication factor: assigned by optimizations that will scale down | ||||||||||||
| 1973 | /// the execution frequency of the original IR. | ||||||||||||
| 1974 | /// Copy Identifier: assigned by optimizations that clones the IR. | ||||||||||||
| 1975 | /// Each copy of the IR will be assigned an identifier. | ||||||||||||
| 1976 | /// | ||||||||||||
| 1977 | /// Encoding: | ||||||||||||
| 1978 | /// | ||||||||||||
| 1979 | /// The above 3 components are encoded into a 32bit unsigned integer in | ||||||||||||
| 1980 | /// order. If the lowest bit is 1, the current component is empty, and the | ||||||||||||
| 1981 | /// next component will start in the next bit. Otherwise, the current | ||||||||||||
| 1982 | /// component is non-empty, and its content starts in the next bit. The | ||||||||||||
| 1983 | /// value of each components is either 5 bit or 12 bit: if the 7th bit | ||||||||||||
| 1984 | /// is 0, the bit 2~6 (5 bits) are used to represent the component; if the | ||||||||||||
| 1985 | /// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to | ||||||||||||
| 1986 | /// represent the component. Thus, the number of bits used for a component | ||||||||||||
| 1987 | /// is either 0 (if it and all the next components are empty); 1 - if it is | ||||||||||||
| 1988 | /// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both | ||||||||||||
| 1989 | /// 0); or 14, if its value is up to and including 0x1ff. Note that the last | ||||||||||||
| 1990 | /// component is also capped at 0x1ff, even in the case when both first | ||||||||||||
| 1991 | /// components are 0, and we'd technically have 29 bits available. | ||||||||||||
| 1992 | /// | ||||||||||||
| 1993 | /// For precise control over the data being encoded in the discriminator, | ||||||||||||
| 1994 | /// use encodeDiscriminator/decodeDiscriminator. | ||||||||||||
| 1995 | |||||||||||||
| 1996 | inline unsigned getDiscriminator() const; | ||||||||||||
| 1997 | |||||||||||||
| 1998 | // For the regular discriminator, it stands for all empty components if all | ||||||||||||
| 1999 | // the lowest 3 bits are non-zero and all higher 29 bits are unused(zero by | ||||||||||||
| 2000 | // default). Here we fully leverage the higher 29 bits for pseudo probe use. | ||||||||||||
| 2001 | // This is the format: | ||||||||||||
| 2002 | // [2:0] - 0x7 | ||||||||||||
| 2003 | // [31:3] - pseudo probe fields guaranteed to be non-zero as a whole | ||||||||||||
| 2004 | // So if the lower 3 bits is non-zero and the others has at least one | ||||||||||||
| 2005 | // non-zero bit, it guarantees to be a pseudo probe discriminator | ||||||||||||
| 2006 | inline static bool isPseudoProbeDiscriminator(unsigned Discriminator) { | ||||||||||||
| 2007 | return ((Discriminator & 0x7) == 0x7) && (Discriminator & 0xFFFFFFF8); | ||||||||||||
| 2008 | } | ||||||||||||
| 2009 | |||||||||||||
| 2010 | /// Returns a new DILocation with updated \p Discriminator. | ||||||||||||
| 2011 | inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const; | ||||||||||||
| 2012 | |||||||||||||
| 2013 | /// Returns a new DILocation with updated base discriminator \p BD. Only the | ||||||||||||
| 2014 | /// base discriminator is set in the new DILocation, the other encoded values | ||||||||||||
| 2015 | /// are elided. | ||||||||||||
| 2016 | /// If the discriminator cannot be encoded, the function returns std::nullopt. | ||||||||||||
| 2017 | inline std::optional<const DILocation *> | ||||||||||||
| 2018 | cloneWithBaseDiscriminator(unsigned BD) const; | ||||||||||||
| 2019 | |||||||||||||
| 2020 | /// Returns the duplication factor stored in the discriminator, or 1 if no | ||||||||||||
| 2021 | /// duplication factor (or 0) is encoded. | ||||||||||||
| 2022 | inline unsigned getDuplicationFactor() const; | ||||||||||||
| 2023 | |||||||||||||
| 2024 | /// Returns the copy identifier stored in the discriminator. | ||||||||||||
| 2025 | inline unsigned getCopyIdentifier() const; | ||||||||||||
| 2026 | |||||||||||||
| 2027 | /// Returns the base discriminator stored in the discriminator. | ||||||||||||
| 2028 | inline unsigned getBaseDiscriminator() const; | ||||||||||||
| 2029 | |||||||||||||
| 2030 | /// Returns a new DILocation with duplication factor \p DF * current | ||||||||||||
| 2031 | /// duplication factor encoded in the discriminator. The current duplication | ||||||||||||
| 2032 | /// factor is as defined by getDuplicationFactor(). | ||||||||||||
| 2033 | /// Returns std::nullopt if encoding failed. | ||||||||||||
| 2034 | inline std::optional<const DILocation *> | ||||||||||||
| 2035 | cloneByMultiplyingDuplicationFactor(unsigned DF) const; | ||||||||||||
| 2036 | |||||||||||||
| 2037 | /// When two instructions are combined into a single instruction we also | ||||||||||||
| 2038 | /// need to combine the original locations into a single location. | ||||||||||||
| 2039 | /// When the locations are the same we can use either location. | ||||||||||||
| 2040 | /// When they differ, we need a third location which is distinct from either. | ||||||||||||
| 2041 | /// If they share a common scope, use this scope and compare the line/column | ||||||||||||
| 2042 | /// pair of the locations with the common scope: | ||||||||||||
| 2043 | /// * if both match, keep the line and column; | ||||||||||||
| 2044 | /// * if only the line number matches, keep the line and set the column as 0; | ||||||||||||
| 2045 | /// * otherwise set line and column as 0. | ||||||||||||
| 2046 | /// If they do not share a common scope the location is ambiguous and can't be | ||||||||||||
| 2047 | /// represented in a line entry. In this case, set line and column as 0 and | ||||||||||||
| 2048 | /// use the scope of any location. | ||||||||||||
| 2049 | /// | ||||||||||||
| 2050 | /// \p LocA \p LocB: The locations to be merged. | ||||||||||||
| 2051 | static const DILocation *getMergedLocation(const DILocation *LocA, | ||||||||||||
| 2052 | const DILocation *LocB); | ||||||||||||
| 2053 | |||||||||||||
| 2054 | /// Try to combine the vector of locations passed as input in a single one. | ||||||||||||
| 2055 | /// This function applies getMergedLocation() repeatedly left-to-right. | ||||||||||||
| 2056 | /// | ||||||||||||
| 2057 | /// \p Locs: The locations to be merged. | ||||||||||||
| 2058 | static const DILocation * | ||||||||||||
| 2059 | getMergedLocations(ArrayRef<const DILocation *> Locs); | ||||||||||||
| 2060 | |||||||||||||
| 2061 | /// Return the masked discriminator value for an input discrimnator value D | ||||||||||||
| 2062 | /// (i.e. zero out the (B+1)-th and above bits for D (B is 0-base). | ||||||||||||
| 2063 | // Example: an input of (0x1FF, 7) returns 0xFF. | ||||||||||||
| 2064 | static unsigned getMaskedDiscriminator(unsigned D, unsigned B) { | ||||||||||||
| 2065 | return (D & getN1Bits(B)); | ||||||||||||
| 2066 | } | ||||||||||||
| 2067 | |||||||||||||
| 2068 | /// Return the bits used for base discriminators. | ||||||||||||
| 2069 | static unsigned getBaseDiscriminatorBits() { return getBaseFSBitEnd(); } | ||||||||||||
| 2070 | |||||||||||||
| 2071 | /// Returns the base discriminator for a given encoded discriminator \p D. | ||||||||||||
| 2072 | static unsigned | ||||||||||||
| 2073 | getBaseDiscriminatorFromDiscriminator(unsigned D, | ||||||||||||
| 2074 | bool IsFSDiscriminator = false) { | ||||||||||||
| 2075 | if (IsFSDiscriminator) | ||||||||||||
| 2076 | return getMaskedDiscriminator(D, getBaseDiscriminatorBits()); | ||||||||||||
| 2077 | return getUnsignedFromPrefixEncoding(D); | ||||||||||||
| 2078 | } | ||||||||||||
| 2079 | |||||||||||||
| 2080 | /// Raw encoding of the discriminator. APIs such as cloneWithDuplicationFactor | ||||||||||||
| 2081 | /// have certain special case behavior (e.g. treating empty duplication factor | ||||||||||||
| 2082 | /// as the value '1'). | ||||||||||||
| 2083 | /// This API, in conjunction with cloneWithDiscriminator, may be used to | ||||||||||||
| 2084 | /// encode the raw values provided. | ||||||||||||
| 2085 | /// | ||||||||||||
| 2086 | /// \p BD: base discriminator | ||||||||||||
| 2087 | /// \p DF: duplication factor | ||||||||||||
| 2088 | /// \p CI: copy index | ||||||||||||
| 2089 | /// | ||||||||||||
| 2090 | /// The return is std::nullopt if the values cannot be encoded in 32 bits - | ||||||||||||
| 2091 | /// for example, values for BD or DF larger than 12 bits. Otherwise, the | ||||||||||||
| 2092 | /// return is the encoded value. | ||||||||||||
| 2093 | static std::optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, | ||||||||||||
| 2094 | unsigned CI); | ||||||||||||
| 2095 | |||||||||||||
| 2096 | /// Raw decoder for values in an encoded discriminator D. | ||||||||||||
| 2097 | static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, | ||||||||||||
| 2098 | unsigned &CI); | ||||||||||||
| 2099 | |||||||||||||
| 2100 | /// Returns the duplication factor for a given encoded discriminator \p D, or | ||||||||||||
| 2101 | /// 1 if no value or 0 is encoded. | ||||||||||||
| 2102 | static unsigned getDuplicationFactorFromDiscriminator(unsigned D) { | ||||||||||||
| 2103 | if (EnableFSDiscriminator) | ||||||||||||
| 2104 | return 1; | ||||||||||||
| 2105 | D = getNextComponentInDiscriminator(D); | ||||||||||||
| 2106 | unsigned Ret = getUnsignedFromPrefixEncoding(D); | ||||||||||||
| 2107 | if (Ret == 0) | ||||||||||||
| 2108 | return 1; | ||||||||||||
| 2109 | return Ret; | ||||||||||||
| 2110 | } | ||||||||||||
| 2111 | |||||||||||||
| 2112 | /// Returns the copy identifier for a given encoded discriminator \p D. | ||||||||||||
| 2113 | static unsigned getCopyIdentifierFromDiscriminator(unsigned D) { | ||||||||||||
| 2114 | return getUnsignedFromPrefixEncoding( | ||||||||||||
| 2115 | getNextComponentInDiscriminator(getNextComponentInDiscriminator(D))); | ||||||||||||
| 2116 | } | ||||||||||||
| 2117 | |||||||||||||
| 2118 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
| 2119 | Metadata *getRawInlinedAt() const { | ||||||||||||
| 2120 | if (getNumOperands() == 2) | ||||||||||||
| 2121 | return getOperand(1); | ||||||||||||
| 2122 | return nullptr; | ||||||||||||
| 2123 | } | ||||||||||||
| 2124 | |||||||||||||
| 2125 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2126 | return MD->getMetadataID() == DILocationKind; | ||||||||||||
| 2127 | } | ||||||||||||
| 2128 | }; | ||||||||||||
| 2129 | |||||||||||||
| 2130 | class DILexicalBlockBase : public DILocalScope { | ||||||||||||
| 2131 | protected: | ||||||||||||
| 2132 | DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, | ||||||||||||
| 2133 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 2134 | ~DILexicalBlockBase() = default; | ||||||||||||
| 2135 | |||||||||||||
| 2136 | public: | ||||||||||||
| 2137 | DILocalScope *getScope() const { return cast<DILocalScope>(getRawScope()); } | ||||||||||||
| 2138 | |||||||||||||
| 2139 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
| 2140 | |||||||||||||
| 2141 | void replaceScope(DIScope *Scope) { | ||||||||||||
| 2142 | assert(!isUniqued())(static_cast <bool> (!isUniqued()) ? void (0) : __assert_fail ("!isUniqued()", "llvm/include/llvm/IR/DebugInfoMetadata.h", 2142, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 2143 | setOperand(1, Scope); | ||||||||||||
| 2144 | } | ||||||||||||
| 2145 | |||||||||||||
| 2146 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2147 | return MD->getMetadataID() == DILexicalBlockKind || | ||||||||||||
| 2148 | MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
| 2149 | } | ||||||||||||
| 2150 | }; | ||||||||||||
| 2151 | |||||||||||||
| 2152 | class DILexicalBlock : public DILexicalBlockBase { | ||||||||||||
| 2153 | friend class LLVMContextImpl; | ||||||||||||
| 2154 | friend class MDNode; | ||||||||||||
| 2155 | |||||||||||||
| 2156 | unsigned Line; | ||||||||||||
| 2157 | uint16_t Column; | ||||||||||||
| 2158 | |||||||||||||
| 2159 | DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 2160 | unsigned Column, ArrayRef<Metadata *> Ops) | ||||||||||||
| 2161 | : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), | ||||||||||||
| 2162 | Column(Column) { | ||||||||||||
| 2163 | assert(Column < (1u << 16) && "Expected 16-bit column")(static_cast <bool> (Column < (1u << 16) && "Expected 16-bit column") ? void (0) : __assert_fail ("Column < (1u << 16) && \"Expected 16-bit column\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2163, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 2164 | } | ||||||||||||
| 2165 | ~DILexicalBlock() = default; | ||||||||||||
| 2166 | |||||||||||||
| 2167 | static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||||||||||
| 2168 | DIFile *File, unsigned Line, unsigned Column, | ||||||||||||
| 2169 | StorageType Storage, | ||||||||||||
| 2170 | bool ShouldCreate = true) { | ||||||||||||
| 2171 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||||||||||
| 2172 | static_cast<Metadata *>(File), Line, Column, Storage, | ||||||||||||
| 2173 | ShouldCreate); | ||||||||||||
| 2174 | } | ||||||||||||
| 2175 | |||||||||||||
| 2176 | static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
| 2177 | Metadata *File, unsigned Line, unsigned Column, | ||||||||||||
| 2178 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 2179 | |||||||||||||
| 2180 | TempDILexicalBlock cloneImpl() const { | ||||||||||||
| 2181 | return getTemporary(getContext(), getScope(), getFile(), getLine(), | ||||||||||||
| 2182 | getColumn()); | ||||||||||||
| 2183 | } | ||||||||||||
| 2184 | |||||||||||||
| 2185 | public: | ||||||||||||
| 2186 | DEFINE_MDNODE_GET(DILexicalBlock, | ||||||||||||
| 2187 | (DILocalScope * Scope, DIFile *File, unsigned Line, | ||||||||||||
| 2188 | unsigned Column), | ||||||||||||
| 2189 | (Scope, File, Line, Column)) | ||||||||||||
| 2190 | DEFINE_MDNODE_GET(DILexicalBlock, | ||||||||||||
| 2191 | (Metadata * Scope, Metadata *File, unsigned Line, | ||||||||||||
| 2192 | unsigned Column), | ||||||||||||
| 2193 | (Scope, File, Line, Column)) | ||||||||||||
| 2194 | |||||||||||||
| 2195 | TempDILexicalBlock clone() const { return cloneImpl(); } | ||||||||||||
| 2196 | |||||||||||||
| 2197 | unsigned getLine() const { return Line; } | ||||||||||||
| 2198 | unsigned getColumn() const { return Column; } | ||||||||||||
| 2199 | |||||||||||||
| 2200 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2201 | return MD->getMetadataID() == DILexicalBlockKind; | ||||||||||||
| 2202 | } | ||||||||||||
| 2203 | }; | ||||||||||||
| 2204 | |||||||||||||
| 2205 | class DILexicalBlockFile : public DILexicalBlockBase { | ||||||||||||
| 2206 | friend class LLVMContextImpl; | ||||||||||||
| 2207 | friend class MDNode; | ||||||||||||
| 2208 | |||||||||||||
| 2209 | unsigned Discriminator; | ||||||||||||
| 2210 | |||||||||||||
| 2211 | DILexicalBlockFile(LLVMContext &C, StorageType Storage, | ||||||||||||
| 2212 | unsigned Discriminator, ArrayRef<Metadata *> Ops) | ||||||||||||
| 2213 | : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), | ||||||||||||
| 2214 | Discriminator(Discriminator) {} | ||||||||||||
| 2215 | ~DILexicalBlockFile() = default; | ||||||||||||
| 2216 | |||||||||||||
| 2217 | static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, | ||||||||||||
| 2218 | DIFile *File, unsigned Discriminator, | ||||||||||||
| 2219 | StorageType Storage, | ||||||||||||
| 2220 | bool ShouldCreate = true) { | ||||||||||||
| 2221 | return getImpl(Context, static_cast<Metadata *>(Scope), | ||||||||||||
| 2222 | static_cast<Metadata *>(File), Discriminator, Storage, | ||||||||||||
| 2223 | ShouldCreate); | ||||||||||||
| 2224 | } | ||||||||||||
| 2225 | |||||||||||||
| 2226 | static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
| 2227 | Metadata *File, unsigned Discriminator, | ||||||||||||
| 2228 | StorageType Storage, | ||||||||||||
| 2229 | bool ShouldCreate = true); | ||||||||||||
| 2230 | |||||||||||||
| 2231 | TempDILexicalBlockFile cloneImpl() const { | ||||||||||||
| 2232 | return getTemporary(getContext(), getScope(), getFile(), | ||||||||||||
| 2233 | getDiscriminator()); | ||||||||||||
| 2234 | } | ||||||||||||
| 2235 | |||||||||||||
| 2236 | public: | ||||||||||||
| 2237 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||||||||||
| 2238 | (DILocalScope * Scope, DIFile *File, | ||||||||||||
| 2239 | unsigned Discriminator), | ||||||||||||
| 2240 | (Scope, File, Discriminator)) | ||||||||||||
| 2241 | DEFINE_MDNODE_GET(DILexicalBlockFile, | ||||||||||||
| 2242 | (Metadata * Scope, Metadata *File, unsigned Discriminator), | ||||||||||||
| 2243 | (Scope, File, Discriminator)) | ||||||||||||
| 2244 | |||||||||||||
| 2245 | TempDILexicalBlockFile clone() const { return cloneImpl(); } | ||||||||||||
| 2246 | unsigned getDiscriminator() const { return Discriminator; } | ||||||||||||
| 2247 | |||||||||||||
| 2248 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2249 | return MD->getMetadataID() == DILexicalBlockFileKind; | ||||||||||||
| 2250 | } | ||||||||||||
| 2251 | }; | ||||||||||||
| 2252 | |||||||||||||
| 2253 | unsigned DILocation::getDiscriminator() const { | ||||||||||||
| 2254 | if (auto *F = dyn_cast<DILexicalBlockFile>(getScope())) | ||||||||||||
| 2255 | return F->getDiscriminator(); | ||||||||||||
| 2256 | return 0; | ||||||||||||
| 2257 | } | ||||||||||||
| 2258 | |||||||||||||
| 2259 | const DILocation * | ||||||||||||
| 2260 | DILocation::cloneWithDiscriminator(unsigned Discriminator) const { | ||||||||||||
| 2261 | DIScope *Scope = getScope(); | ||||||||||||
| 2262 | // Skip all parent DILexicalBlockFile that already have a discriminator | ||||||||||||
| 2263 | // assigned. We do not want to have nested DILexicalBlockFiles that have | ||||||||||||
| 2264 | // mutliple discriminators because only the leaf DILexicalBlockFile's | ||||||||||||
| 2265 | // dominator will be used. | ||||||||||||
| 2266 | for (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope); | ||||||||||||
| 2267 | LBF && LBF->getDiscriminator() != 0; | ||||||||||||
| 2268 | LBF = dyn_cast<DILexicalBlockFile>(Scope)) | ||||||||||||
| 2269 | Scope = LBF->getScope(); | ||||||||||||
| 2270 | DILexicalBlockFile *NewScope = | ||||||||||||
| 2271 | DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator); | ||||||||||||
| 2272 | return DILocation::get(getContext(), getLine(), getColumn(), NewScope, | ||||||||||||
| 2273 | getInlinedAt()); | ||||||||||||
| 2274 | } | ||||||||||||
| 2275 | |||||||||||||
| 2276 | unsigned DILocation::getBaseDiscriminator() const { | ||||||||||||
| 2277 | return getBaseDiscriminatorFromDiscriminator(getDiscriminator(), | ||||||||||||
| 2278 | EnableFSDiscriminator); | ||||||||||||
| 2279 | } | ||||||||||||
| 2280 | |||||||||||||
| 2281 | unsigned DILocation::getDuplicationFactor() const { | ||||||||||||
| 2282 | return getDuplicationFactorFromDiscriminator(getDiscriminator()); | ||||||||||||
| 2283 | } | ||||||||||||
| 2284 | |||||||||||||
| 2285 | unsigned DILocation::getCopyIdentifier() const { | ||||||||||||
| 2286 | return getCopyIdentifierFromDiscriminator(getDiscriminator()); | ||||||||||||
| 2287 | } | ||||||||||||
| 2288 | |||||||||||||
| 2289 | std::optional<const DILocation *> | ||||||||||||
| 2290 | DILocation::cloneWithBaseDiscriminator(unsigned D) const { | ||||||||||||
| 2291 | unsigned BD, DF, CI; | ||||||||||||
| 2292 | |||||||||||||
| 2293 | if (EnableFSDiscriminator) { | ||||||||||||
| 2294 | BD = getBaseDiscriminator(); | ||||||||||||
| 2295 | if (D == BD) | ||||||||||||
| 2296 | return this; | ||||||||||||
| 2297 | return cloneWithDiscriminator(D); | ||||||||||||
| 2298 | } | ||||||||||||
| 2299 | |||||||||||||
| 2300 | decodeDiscriminator(getDiscriminator(), BD, DF, CI); | ||||||||||||
| 2301 | if (D == BD) | ||||||||||||
| 2302 | return this; | ||||||||||||
| 2303 | if (std::optional<unsigned> Encoded = encodeDiscriminator(D, DF, CI)) | ||||||||||||
| 2304 | return cloneWithDiscriminator(*Encoded); | ||||||||||||
| 2305 | return std::nullopt; | ||||||||||||
| 2306 | } | ||||||||||||
| 2307 | |||||||||||||
| 2308 | std::optional<const DILocation *> | ||||||||||||
| 2309 | DILocation::cloneByMultiplyingDuplicationFactor(unsigned DF) const { | ||||||||||||
| 2310 | assert(!EnableFSDiscriminator && "FSDiscriminator should not call this.")(static_cast <bool> (!EnableFSDiscriminator && "FSDiscriminator should not call this." ) ? void (0) : __assert_fail ("!EnableFSDiscriminator && \"FSDiscriminator should not call this.\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2310, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 2311 | |||||||||||||
| 2312 | DF *= getDuplicationFactor(); | ||||||||||||
| 2313 | if (DF <= 1) | ||||||||||||
| 2314 | return this; | ||||||||||||
| 2315 | |||||||||||||
| 2316 | unsigned BD = getBaseDiscriminator(); | ||||||||||||
| 2317 | unsigned CI = getCopyIdentifier(); | ||||||||||||
| 2318 | if (std::optional<unsigned> D = encodeDiscriminator(BD, DF, CI)) | ||||||||||||
| 2319 | return cloneWithDiscriminator(*D); | ||||||||||||
| 2320 | return std::nullopt; | ||||||||||||
| 2321 | } | ||||||||||||
| 2322 | |||||||||||||
| 2323 | class DINamespace : public DIScope { | ||||||||||||
| 2324 | friend class LLVMContextImpl; | ||||||||||||
| 2325 | friend class MDNode; | ||||||||||||
| 2326 | |||||||||||||
| 2327 | unsigned ExportSymbols : 1; | ||||||||||||
| 2328 | |||||||||||||
| 2329 | DINamespace(LLVMContext &Context, StorageType Storage, bool ExportSymbols, | ||||||||||||
| 2330 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 2331 | ~DINamespace() = default; | ||||||||||||
| 2332 | |||||||||||||
| 2333 | static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
| 2334 | StringRef Name, bool ExportSymbols, | ||||||||||||
| 2335 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 2336 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
| 2337 | ExportSymbols, Storage, ShouldCreate); | ||||||||||||
| 2338 | } | ||||||||||||
| 2339 | static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
| 2340 | MDString *Name, bool ExportSymbols, | ||||||||||||
| 2341 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 2342 | |||||||||||||
| 2343 | TempDINamespace cloneImpl() const { | ||||||||||||
| 2344 | return getTemporary(getContext(), getScope(), getName(), | ||||||||||||
| 2345 | getExportSymbols()); | ||||||||||||
| 2346 | } | ||||||||||||
| 2347 | |||||||||||||
| 2348 | public: | ||||||||||||
| 2349 | DEFINE_MDNODE_GET(DINamespace, | ||||||||||||
| 2350 | (DIScope * Scope, StringRef Name, bool ExportSymbols), | ||||||||||||
| 2351 | (Scope, Name, ExportSymbols)) | ||||||||||||
| 2352 | DEFINE_MDNODE_GET(DINamespace, | ||||||||||||
| 2353 | (Metadata * Scope, MDString *Name, bool ExportSymbols), | ||||||||||||
| 2354 | (Scope, Name, ExportSymbols)) | ||||||||||||
| 2355 | |||||||||||||
| 2356 | TempDINamespace clone() const { return cloneImpl(); } | ||||||||||||
| 2357 | |||||||||||||
| 2358 | bool getExportSymbols() const { return ExportSymbols; } | ||||||||||||
| 2359 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 2360 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 2361 | |||||||||||||
| 2362 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
| 2363 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 2364 | |||||||||||||
| 2365 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2366 | return MD->getMetadataID() == DINamespaceKind; | ||||||||||||
| 2367 | } | ||||||||||||
| 2368 | }; | ||||||||||||
| 2369 | |||||||||||||
| 2370 | /// Represents a module in the programming language, for example, a Clang | ||||||||||||
| 2371 | /// module, or a Fortran module. | ||||||||||||
| 2372 | class DIModule : public DIScope { | ||||||||||||
| 2373 | friend class LLVMContextImpl; | ||||||||||||
| 2374 | friend class MDNode; | ||||||||||||
| 2375 | unsigned LineNo; | ||||||||||||
| 2376 | bool IsDecl; | ||||||||||||
| 2377 | |||||||||||||
| 2378 | DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||||||||||
| 2379 | bool IsDecl, ArrayRef<Metadata *> Ops); | ||||||||||||
| 2380 | ~DIModule() = default; | ||||||||||||
| 2381 | |||||||||||||
| 2382 | static DIModule *getImpl(LLVMContext &Context, DIFile *File, DIScope *Scope, | ||||||||||||
| 2383 | StringRef Name, StringRef ConfigurationMacros, | ||||||||||||
| 2384 | StringRef IncludePath, StringRef APINotesFile, | ||||||||||||
| 2385 | unsigned LineNo, bool IsDecl, StorageType Storage, | ||||||||||||
| 2386 | bool ShouldCreate = true) { | ||||||||||||
| 2387 | return getImpl(Context, File, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
| 2388 | getCanonicalMDString(Context, ConfigurationMacros), | ||||||||||||
| 2389 | getCanonicalMDString(Context, IncludePath), | ||||||||||||
| 2390 | getCanonicalMDString(Context, APINotesFile), LineNo, IsDecl, | ||||||||||||
| 2391 | Storage, ShouldCreate); | ||||||||||||
| 2392 | } | ||||||||||||
| 2393 | static DIModule *getImpl(LLVMContext &Context, Metadata *File, | ||||||||||||
| 2394 | Metadata *Scope, MDString *Name, | ||||||||||||
| 2395 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||||||||||
| 2396 | MDString *APINotesFile, unsigned LineNo, bool IsDecl, | ||||||||||||
| 2397 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 2398 | |||||||||||||
| 2399 | TempDIModule cloneImpl() const { | ||||||||||||
| 2400 | return getTemporary(getContext(), getFile(), getScope(), getName(), | ||||||||||||
| 2401 | getConfigurationMacros(), getIncludePath(), | ||||||||||||
| 2402 | getAPINotesFile(), getLineNo(), getIsDecl()); | ||||||||||||
| 2403 | } | ||||||||||||
| 2404 | |||||||||||||
| 2405 | public: | ||||||||||||
| 2406 | DEFINE_MDNODE_GET(DIModule, | ||||||||||||
| 2407 | (DIFile * File, DIScope *Scope, StringRef Name, | ||||||||||||
| 2408 | StringRef ConfigurationMacros, StringRef IncludePath, | ||||||||||||
| 2409 | StringRef APINotesFile, unsigned LineNo, | ||||||||||||
| 2410 | bool IsDecl = false), | ||||||||||||
| 2411 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||||||||||
| 2412 | APINotesFile, LineNo, IsDecl)) | ||||||||||||
| 2413 | DEFINE_MDNODE_GET(DIModule, | ||||||||||||
| 2414 | (Metadata * File, Metadata *Scope, MDString *Name, | ||||||||||||
| 2415 | MDString *ConfigurationMacros, MDString *IncludePath, | ||||||||||||
| 2416 | MDString *APINotesFile, unsigned LineNo, | ||||||||||||
| 2417 | bool IsDecl = false), | ||||||||||||
| 2418 | (File, Scope, Name, ConfigurationMacros, IncludePath, | ||||||||||||
| 2419 | APINotesFile, LineNo, IsDecl)) | ||||||||||||
| 2420 | |||||||||||||
| 2421 | TempDIModule clone() const { return cloneImpl(); } | ||||||||||||
| 2422 | |||||||||||||
| 2423 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 2424 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 2425 | StringRef getConfigurationMacros() const { return getStringOperand(3); } | ||||||||||||
| 2426 | StringRef getIncludePath() const { return getStringOperand(4); } | ||||||||||||
| 2427 | StringRef getAPINotesFile() const { return getStringOperand(5); } | ||||||||||||
| 2428 | unsigned getLineNo() const { return LineNo; } | ||||||||||||
| 2429 | bool getIsDecl() const { return IsDecl; } | ||||||||||||
| 2430 | |||||||||||||
| 2431 | Metadata *getRawScope() const { return getOperand(1); } | ||||||||||||
| 2432 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 2433 | MDString *getRawConfigurationMacros() const { | ||||||||||||
| 2434 | return getOperandAs<MDString>(3); | ||||||||||||
| 2435 | } | ||||||||||||
| 2436 | MDString *getRawIncludePath() const { return getOperandAs<MDString>(4); } | ||||||||||||
| 2437 | MDString *getRawAPINotesFile() const { return getOperandAs<MDString>(5); } | ||||||||||||
| 2438 | |||||||||||||
| 2439 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2440 | return MD->getMetadataID() == DIModuleKind; | ||||||||||||
| 2441 | } | ||||||||||||
| 2442 | }; | ||||||||||||
| 2443 | |||||||||||||
| 2444 | /// Base class for template parameters. | ||||||||||||
| 2445 | class DITemplateParameter : public DINode { | ||||||||||||
| 2446 | protected: | ||||||||||||
| 2447 | bool IsDefault; | ||||||||||||
| 2448 | |||||||||||||
| 2449 | DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, | ||||||||||||
| 2450 | unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops) | ||||||||||||
| 2451 | : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {} | ||||||||||||
| 2452 | ~DITemplateParameter() = default; | ||||||||||||
| 2453 | |||||||||||||
| 2454 | public: | ||||||||||||
| 2455 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
| 2456 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
| 2457 | |||||||||||||
| 2458 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 2459 | Metadata *getRawType() const { return getOperand(1); } | ||||||||||||
| 2460 | bool isDefault() const { return IsDefault; } | ||||||||||||
| 2461 | |||||||||||||
| 2462 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2463 | return MD->getMetadataID() == DITemplateTypeParameterKind || | ||||||||||||
| 2464 | MD->getMetadataID() == DITemplateValueParameterKind; | ||||||||||||
| 2465 | } | ||||||||||||
| 2466 | }; | ||||||||||||
| 2467 | |||||||||||||
| 2468 | class DITemplateTypeParameter : public DITemplateParameter { | ||||||||||||
| 2469 | friend class LLVMContextImpl; | ||||||||||||
| 2470 | friend class MDNode; | ||||||||||||
| 2471 | |||||||||||||
| 2472 | DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, | ||||||||||||
| 2473 | bool IsDefault, ArrayRef<Metadata *> Ops); | ||||||||||||
| 2474 | ~DITemplateTypeParameter() = default; | ||||||||||||
| 2475 | |||||||||||||
| 2476 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, | ||||||||||||
| 2477 | DIType *Type, bool IsDefault, | ||||||||||||
| 2478 | StorageType Storage, | ||||||||||||
| 2479 | bool ShouldCreate = true) { | ||||||||||||
| 2480 | return getImpl(Context, getCanonicalMDString(Context, Name), Type, | ||||||||||||
| 2481 | IsDefault, Storage, ShouldCreate); | ||||||||||||
| 2482 | } | ||||||||||||
| 2483 | static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, | ||||||||||||
| 2484 | Metadata *Type, bool IsDefault, | ||||||||||||
| 2485 | StorageType Storage, | ||||||||||||
| 2486 | bool ShouldCreate = true); | ||||||||||||
| 2487 | |||||||||||||
| 2488 | TempDITemplateTypeParameter cloneImpl() const { | ||||||||||||
| 2489 | return getTemporary(getContext(), getName(), getType(), isDefault()); | ||||||||||||
| 2490 | } | ||||||||||||
| 2491 | |||||||||||||
| 2492 | public: | ||||||||||||
| 2493 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||||||||||
| 2494 | (StringRef Name, DIType *Type, bool IsDefault), | ||||||||||||
| 2495 | (Name, Type, IsDefault)) | ||||||||||||
| 2496 | DEFINE_MDNODE_GET(DITemplateTypeParameter, | ||||||||||||
| 2497 | (MDString * Name, Metadata *Type, bool IsDefault), | ||||||||||||
| 2498 | (Name, Type, IsDefault)) | ||||||||||||
| 2499 | |||||||||||||
| 2500 | TempDITemplateTypeParameter clone() const { return cloneImpl(); } | ||||||||||||
| 2501 | |||||||||||||
| 2502 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2503 | return MD->getMetadataID() == DITemplateTypeParameterKind; | ||||||||||||
| 2504 | } | ||||||||||||
| 2505 | }; | ||||||||||||
| 2506 | |||||||||||||
| 2507 | class DITemplateValueParameter : public DITemplateParameter { | ||||||||||||
| 2508 | friend class LLVMContextImpl; | ||||||||||||
| 2509 | friend class MDNode; | ||||||||||||
| 2510 | |||||||||||||
| 2511 | DITemplateValueParameter(LLVMContext &Context, StorageType Storage, | ||||||||||||
| 2512 | unsigned Tag, bool IsDefault, | ||||||||||||
| 2513 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 2514 | : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, | ||||||||||||
| 2515 | IsDefault, Ops) {} | ||||||||||||
| 2516 | ~DITemplateValueParameter() = default; | ||||||||||||
| 2517 | |||||||||||||
| 2518 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 2519 | StringRef Name, DIType *Type, | ||||||||||||
| 2520 | bool IsDefault, Metadata *Value, | ||||||||||||
| 2521 | StorageType Storage, | ||||||||||||
| 2522 | bool ShouldCreate = true) { | ||||||||||||
| 2523 | return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, | ||||||||||||
| 2524 | IsDefault, Value, Storage, ShouldCreate); | ||||||||||||
| 2525 | } | ||||||||||||
| 2526 | static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 2527 | MDString *Name, Metadata *Type, | ||||||||||||
| 2528 | bool IsDefault, Metadata *Value, | ||||||||||||
| 2529 | StorageType Storage, | ||||||||||||
| 2530 | bool ShouldCreate = true); | ||||||||||||
| 2531 | |||||||||||||
| 2532 | TempDITemplateValueParameter cloneImpl() const { | ||||||||||||
| 2533 | return getTemporary(getContext(), getTag(), getName(), getType(), | ||||||||||||
| 2534 | isDefault(), getValue()); | ||||||||||||
| 2535 | } | ||||||||||||
| 2536 | |||||||||||||
| 2537 | public: | ||||||||||||
| 2538 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||||||||||
| 2539 | (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault, | ||||||||||||
| 2540 | Metadata *Value), | ||||||||||||
| 2541 | (Tag, Name, Type, IsDefault, Value)) | ||||||||||||
| 2542 | DEFINE_MDNODE_GET(DITemplateValueParameter, | ||||||||||||
| 2543 | (unsigned Tag, MDString *Name, Metadata *Type, | ||||||||||||
| 2544 | bool IsDefault, Metadata *Value), | ||||||||||||
| 2545 | (Tag, Name, Type, IsDefault, Value)) | ||||||||||||
| 2546 | |||||||||||||
| 2547 | TempDITemplateValueParameter clone() const { return cloneImpl(); } | ||||||||||||
| 2548 | |||||||||||||
| 2549 | Metadata *getValue() const { return getOperand(2); } | ||||||||||||
| 2550 | |||||||||||||
| 2551 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2552 | return MD->getMetadataID() == DITemplateValueParameterKind; | ||||||||||||
| 2553 | } | ||||||||||||
| 2554 | }; | ||||||||||||
| 2555 | |||||||||||||
| 2556 | /// Base class for variables. | ||||||||||||
| 2557 | class DIVariable : public DINode { | ||||||||||||
| 2558 | unsigned Line; | ||||||||||||
| 2559 | uint32_t AlignInBits; | ||||||||||||
| 2560 | |||||||||||||
| 2561 | protected: | ||||||||||||
| 2562 | DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, signed Line, | ||||||||||||
| 2563 | ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0); | ||||||||||||
| 2564 | ~DIVariable() = default; | ||||||||||||
| 2565 | |||||||||||||
| 2566 | public: | ||||||||||||
| 2567 | unsigned getLine() const { return Line; } | ||||||||||||
| 2568 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 2569 | StringRef getName() const { return getStringOperand(1); } | ||||||||||||
| 2570 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 2571 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
| 2572 | uint32_t getAlignInBits() const { return AlignInBits; } | ||||||||||||
| 2573 | uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT8; } | ||||||||||||
| 2574 | /// Determines the size of the variable's type. | ||||||||||||
| 2575 | std::optional<uint64_t> getSizeInBits() const; | ||||||||||||
| 2576 | |||||||||||||
| 2577 | /// Return the signedness of this variable's type, or std::nullopt if this | ||||||||||||
| 2578 | /// type is neither signed nor unsigned. | ||||||||||||
| 2579 | std::optional<DIBasicType::Signedness> getSignedness() const { | ||||||||||||
| 2580 | if (auto *BT = dyn_cast<DIBasicType>(getType())) | ||||||||||||
| 2581 | return BT->getSignedness(); | ||||||||||||
| 2582 | return std::nullopt; | ||||||||||||
| 2583 | } | ||||||||||||
| 2584 | |||||||||||||
| 2585 | StringRef getFilename() const { | ||||||||||||
| 2586 | if (auto *F = getFile()) | ||||||||||||
| 2587 | return F->getFilename(); | ||||||||||||
| 2588 | return ""; | ||||||||||||
| 2589 | } | ||||||||||||
| 2590 | |||||||||||||
| 2591 | StringRef getDirectory() const { | ||||||||||||
| 2592 | if (auto *F = getFile()) | ||||||||||||
| 2593 | return F->getDirectory(); | ||||||||||||
| 2594 | return ""; | ||||||||||||
| 2595 | } | ||||||||||||
| 2596 | |||||||||||||
| 2597 | std::optional<StringRef> getSource() const { | ||||||||||||
| 2598 | if (auto *F = getFile()) | ||||||||||||
| 2599 | return F->getSource(); | ||||||||||||
| 2600 | return std::nullopt; | ||||||||||||
| 2601 | } | ||||||||||||
| 2602 | |||||||||||||
| 2603 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
| 2604 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||||||||||
| 2605 | Metadata *getRawFile() const { return getOperand(2); } | ||||||||||||
| 2606 | Metadata *getRawType() const { return getOperand(3); } | ||||||||||||
| 2607 | |||||||||||||
| 2608 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2609 | return MD->getMetadataID() == DILocalVariableKind || | ||||||||||||
| 2610 | MD->getMetadataID() == DIGlobalVariableKind; | ||||||||||||
| 2611 | } | ||||||||||||
| 2612 | }; | ||||||||||||
| 2613 | |||||||||||||
| 2614 | /// DWARF expression. | ||||||||||||
| 2615 | /// | ||||||||||||
| 2616 | /// This is (almost) a DWARF expression that modifies the location of a | ||||||||||||
| 2617 | /// variable, or the location of a single piece of a variable, or (when using | ||||||||||||
| 2618 | /// DW_OP_stack_value) is the constant variable value. | ||||||||||||
| 2619 | /// | ||||||||||||
| 2620 | /// TODO: Co-allocate the expression elements. | ||||||||||||
| 2621 | /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary | ||||||||||||
| 2622 | /// storage types. | ||||||||||||
| 2623 | class DIExpression : public MDNode { | ||||||||||||
| 2624 | friend class LLVMContextImpl; | ||||||||||||
| 2625 | friend class MDNode; | ||||||||||||
| 2626 | |||||||||||||
| 2627 | std::vector<uint64_t> Elements; | ||||||||||||
| 2628 | |||||||||||||
| 2629 | DIExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) | ||||||||||||
| 2630 | : MDNode(C, DIExpressionKind, Storage, std::nullopt), | ||||||||||||
| 2631 | Elements(Elements.begin(), Elements.end()) {} | ||||||||||||
| 2632 | ~DIExpression() = default; | ||||||||||||
| 2633 | |||||||||||||
| 2634 | static DIExpression *getImpl(LLVMContext &Context, | ||||||||||||
| 2635 | ArrayRef<uint64_t> Elements, StorageType Storage, | ||||||||||||
| 2636 | bool ShouldCreate = true); | ||||||||||||
| 2637 | |||||||||||||
| 2638 | TempDIExpression cloneImpl() const { | ||||||||||||
| 2639 | return getTemporary(getContext(), getElements()); | ||||||||||||
| 2640 | } | ||||||||||||
| 2641 | |||||||||||||
| 2642 | public: | ||||||||||||
| 2643 | DEFINE_MDNODE_GET(DIExpression, (ArrayRef<uint64_t> Elements), (Elements)) | ||||||||||||
| 2644 | |||||||||||||
| 2645 | TempDIExpression clone() const { return cloneImpl(); } | ||||||||||||
| 2646 | |||||||||||||
| 2647 | ArrayRef<uint64_t> getElements() const { return Elements; } | ||||||||||||
| 2648 | |||||||||||||
| 2649 | unsigned getNumElements() const { return Elements.size(); } | ||||||||||||
| 2650 | |||||||||||||
| 2651 | uint64_t getElement(unsigned I) const { | ||||||||||||
| 2652 | assert(I < Elements.size() && "Index out of range")(static_cast <bool> (I < Elements.size() && "Index out of range" ) ? void (0) : __assert_fail ("I < Elements.size() && \"Index out of range\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 2652, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 2653 | return Elements[I]; | ||||||||||||
| 2654 | } | ||||||||||||
| 2655 | |||||||||||||
| 2656 | enum SignedOrUnsignedConstant { SignedConstant, UnsignedConstant }; | ||||||||||||
| 2657 | /// Determine whether this represents a constant value, if so | ||||||||||||
| 2658 | // return it's sign information. | ||||||||||||
| 2659 | std::optional<SignedOrUnsignedConstant> isConstant() const; | ||||||||||||
| 2660 | |||||||||||||
| 2661 | /// Return the number of unique location operands referred to (via | ||||||||||||
| 2662 | /// DW_OP_LLVM_arg) in this expression; this is not necessarily the number of | ||||||||||||
| 2663 | /// instances of DW_OP_LLVM_arg within the expression. | ||||||||||||
| 2664 | /// For example, for the expression: | ||||||||||||
| 2665 | /// (DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_plus, | ||||||||||||
| 2666 | /// DW_OP_LLVM_arg 0, DW_OP_mul) | ||||||||||||
| 2667 | /// This function would return 2, as there are two unique location operands | ||||||||||||
| 2668 | /// (0 and 1). | ||||||||||||
| 2669 | uint64_t getNumLocationOperands() const; | ||||||||||||
| 2670 | |||||||||||||
| 2671 | using element_iterator = ArrayRef<uint64_t>::iterator; | ||||||||||||
| 2672 | |||||||||||||
| 2673 | element_iterator elements_begin() const { return getElements().begin(); } | ||||||||||||
| 2674 | element_iterator elements_end() const { return getElements().end(); } | ||||||||||||
| 2675 | |||||||||||||
| 2676 | /// A lightweight wrapper around an expression operand. | ||||||||||||
| 2677 | /// | ||||||||||||
| 2678 | /// TODO: Store arguments directly and change \a DIExpression to store a | ||||||||||||
| 2679 | /// range of these. | ||||||||||||
| 2680 | class ExprOperand { | ||||||||||||
| 2681 | const uint64_t *Op = nullptr; | ||||||||||||
| 2682 | |||||||||||||
| 2683 | public: | ||||||||||||
| 2684 | ExprOperand() = default; | ||||||||||||
| 2685 | explicit ExprOperand(const uint64_t *Op) : Op(Op) {} | ||||||||||||
| 2686 | |||||||||||||
| 2687 | const uint64_t *get() const { return Op; } | ||||||||||||
| 2688 | |||||||||||||
| 2689 | /// Get the operand code. | ||||||||||||
| 2690 | uint64_t getOp() const { return *Op; } | ||||||||||||
| 2691 | |||||||||||||
| 2692 | /// Get an argument to the operand. | ||||||||||||
| 2693 | /// | ||||||||||||
| 2694 | /// Never returns the operand itself. | ||||||||||||
| 2695 | uint64_t getArg(unsigned I) const { return Op[I + 1]; } | ||||||||||||
| 2696 | |||||||||||||
| 2697 | unsigned getNumArgs() const { return getSize() - 1; } | ||||||||||||
| 2698 | |||||||||||||
| 2699 | /// Return the size of the operand. | ||||||||||||
| 2700 | /// | ||||||||||||
| 2701 | /// Return the number of elements in the operand (1 + args). | ||||||||||||
| 2702 | unsigned getSize() const; | ||||||||||||
| 2703 | |||||||||||||
| 2704 | /// Append the elements of this operand to \p V. | ||||||||||||
| 2705 | void appendToVector(SmallVectorImpl<uint64_t> &V) const { | ||||||||||||
| 2706 | V.append(get(), get() + getSize()); | ||||||||||||
| 2707 | } | ||||||||||||
| 2708 | }; | ||||||||||||
| 2709 | |||||||||||||
| 2710 | /// An iterator for expression operands. | ||||||||||||
| 2711 | class expr_op_iterator { | ||||||||||||
| 2712 | ExprOperand Op; | ||||||||||||
| 2713 | |||||||||||||
| 2714 | public: | ||||||||||||
| 2715 | using iterator_category = std::input_iterator_tag; | ||||||||||||
| 2716 | using value_type = ExprOperand; | ||||||||||||
| 2717 | using difference_type = std::ptrdiff_t; | ||||||||||||
| 2718 | using pointer = value_type *; | ||||||||||||
| 2719 | using reference = value_type &; | ||||||||||||
| 2720 | |||||||||||||
| 2721 | expr_op_iterator() = default; | ||||||||||||
| 2722 | explicit expr_op_iterator(element_iterator I) : Op(I) {} | ||||||||||||
| 2723 | |||||||||||||
| 2724 | element_iterator getBase() const { return Op.get(); } | ||||||||||||
| 2725 | const ExprOperand &operator*() const { return Op; } | ||||||||||||
| 2726 | const ExprOperand *operator->() const { return &Op; } | ||||||||||||
| 2727 | |||||||||||||
| 2728 | expr_op_iterator &operator++() { | ||||||||||||
| 2729 | increment(); | ||||||||||||
| 2730 | return *this; | ||||||||||||
| 2731 | } | ||||||||||||
| 2732 | expr_op_iterator operator++(int) { | ||||||||||||
| 2733 | expr_op_iterator T(*this); | ||||||||||||
| 2734 | increment(); | ||||||||||||
| 2735 | return T; | ||||||||||||
| 2736 | } | ||||||||||||
| 2737 | |||||||||||||
| 2738 | /// Get the next iterator. | ||||||||||||
| 2739 | /// | ||||||||||||
| 2740 | /// \a std::next() doesn't work because this is technically an | ||||||||||||
| 2741 | /// input_iterator, but it's a perfectly valid operation. This is an | ||||||||||||
| 2742 | /// accessor to provide the same functionality. | ||||||||||||
| 2743 | expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } | ||||||||||||
| 2744 | |||||||||||||
| 2745 | bool operator==(const expr_op_iterator &X) const { | ||||||||||||
| 2746 | return getBase() == X.getBase(); | ||||||||||||
| 2747 | } | ||||||||||||
| 2748 | bool operator!=(const expr_op_iterator &X) const { | ||||||||||||
| 2749 | return getBase() != X.getBase(); | ||||||||||||
| 2750 | } | ||||||||||||
| 2751 | |||||||||||||
| 2752 | private: | ||||||||||||
| 2753 | void increment() { Op = ExprOperand(getBase() + Op.getSize()); } | ||||||||||||
| 2754 | }; | ||||||||||||
| 2755 | |||||||||||||
| 2756 | /// Visit the elements via ExprOperand wrappers. | ||||||||||||
| 2757 | /// | ||||||||||||
| 2758 | /// These range iterators visit elements through \a ExprOperand wrappers. | ||||||||||||
| 2759 | /// This is not guaranteed to be a valid range unless \a isValid() gives \c | ||||||||||||
| 2760 | /// true. | ||||||||||||
| 2761 | /// | ||||||||||||
| 2762 | /// \pre \a isValid() gives \c true. | ||||||||||||
| 2763 | /// @{ | ||||||||||||
| 2764 | expr_op_iterator expr_op_begin() const { | ||||||||||||
| 2765 | return expr_op_iterator(elements_begin()); | ||||||||||||
| 2766 | } | ||||||||||||
| 2767 | expr_op_iterator expr_op_end() const { | ||||||||||||
| 2768 | return expr_op_iterator(elements_end()); | ||||||||||||
| 2769 | } | ||||||||||||
| 2770 | iterator_range<expr_op_iterator> expr_ops() const { | ||||||||||||
| 2771 | return {expr_op_begin(), expr_op_end()}; | ||||||||||||
| 2772 | } | ||||||||||||
| 2773 | /// @} | ||||||||||||
| 2774 | |||||||||||||
| 2775 | bool isValid() const; | ||||||||||||
| 2776 | |||||||||||||
| 2777 | static bool classof(const Metadata *MD) { | ||||||||||||
| 2778 | return MD->getMetadataID() == DIExpressionKind; | ||||||||||||
| 2779 | } | ||||||||||||
| 2780 | |||||||||||||
| 2781 | /// Return whether the first element a DW_OP_deref. | ||||||||||||
| 2782 | bool startsWithDeref() const; | ||||||||||||
| 2783 | |||||||||||||
| 2784 | /// Return whether there is exactly one operator and it is a DW_OP_deref; | ||||||||||||
| 2785 | bool isDeref() const; | ||||||||||||
| 2786 | |||||||||||||
| 2787 | /// Holds the characteristics of one fragment of a larger variable. | ||||||||||||
| 2788 | struct FragmentInfo { | ||||||||||||
| 2789 | FragmentInfo() = default; | ||||||||||||
| 2790 | FragmentInfo(uint64_t SizeInBits, uint64_t OffsetInBits) | ||||||||||||
| 2791 | : SizeInBits(SizeInBits), OffsetInBits(OffsetInBits) {} | ||||||||||||
| 2792 | uint64_t SizeInBits; | ||||||||||||
| 2793 | uint64_t OffsetInBits; | ||||||||||||
| 2794 | /// Return the index of the first bit of the fragment. | ||||||||||||
| 2795 | uint64_t startInBits() const { return OffsetInBits; } | ||||||||||||
| 2796 | /// Return the index of the bit after the end of the fragment, e.g. for | ||||||||||||
| 2797 | /// fragment offset=16 and size=32 return their sum, 48. | ||||||||||||
| 2798 | uint64_t endInBits() const { return OffsetInBits + SizeInBits; } | ||||||||||||
| 2799 | |||||||||||||
| 2800 | /// Returns a zero-sized fragment if A and B don't intersect. | ||||||||||||
| 2801 | static DIExpression::FragmentInfo intersect(DIExpression::FragmentInfo A, | ||||||||||||
| 2802 | DIExpression::FragmentInfo B) { | ||||||||||||
| 2803 | uint64_t StartInBits = std::max(A.OffsetInBits, B.OffsetInBits); | ||||||||||||
| 2804 | uint64_t EndInBits = std::min(A.endInBits(), B.endInBits()); | ||||||||||||
| 2805 | if (EndInBits <= StartInBits) | ||||||||||||
| 2806 | return {0, 0}; | ||||||||||||
| 2807 | return DIExpression::FragmentInfo(EndInBits - StartInBits, StartInBits); | ||||||||||||
| 2808 | } | ||||||||||||
| 2809 | }; | ||||||||||||
| 2810 | |||||||||||||
| 2811 | /// Retrieve the details of this fragment expression. | ||||||||||||
| 2812 | static std::optional<FragmentInfo> getFragmentInfo(expr_op_iterator Start, | ||||||||||||
| 2813 | expr_op_iterator End); | ||||||||||||
| 2814 | |||||||||||||
| 2815 | /// Retrieve the details of this fragment expression. | ||||||||||||
| 2816 | std::optional<FragmentInfo> getFragmentInfo() const { | ||||||||||||
| 2817 | return getFragmentInfo(expr_op_begin(), expr_op_end()); | ||||||||||||
| 2818 | } | ||||||||||||
| 2819 | |||||||||||||
| 2820 | /// Return whether this is a piece of an aggregate variable. | ||||||||||||
| 2821 | bool isFragment() const { return getFragmentInfo().has_value(); } | ||||||||||||
| 2822 | |||||||||||||
| 2823 | /// Return whether this is an implicit location description. | ||||||||||||
| 2824 | bool isImplicit() const; | ||||||||||||
| 2825 | |||||||||||||
| 2826 | /// Return whether the location is computed on the expression stack, meaning | ||||||||||||
| 2827 | /// it cannot be a simple register location. | ||||||||||||
| 2828 | bool isComplex() const; | ||||||||||||
| 2829 | |||||||||||||
| 2830 | /// Return whether the evaluated expression makes use of a single location at | ||||||||||||
| 2831 | /// the start of the expression, i.e. if it contains only a single | ||||||||||||
| 2832 | /// DW_OP_LLVM_arg op as its first operand, or if it contains none. | ||||||||||||
| 2833 | bool isSingleLocationExpression() const; | ||||||||||||
| 2834 | |||||||||||||
| 2835 | /// Removes all elements from \p Expr that do not apply to an undef debug | ||||||||||||
| 2836 | /// value, which includes every operator that computes the value/location on | ||||||||||||
| 2837 | /// the DWARF stack, including any DW_OP_LLVM_arg elements (making the result | ||||||||||||
| 2838 | /// of this function always a single-location expression) while leaving | ||||||||||||
| 2839 | /// everything that defines what the computed value applies to, i.e. the | ||||||||||||
| 2840 | /// fragment information. | ||||||||||||
| 2841 | static const DIExpression *convertToUndefExpression(const DIExpression *Expr); | ||||||||||||
| 2842 | |||||||||||||
| 2843 | /// If \p Expr is a non-variadic expression (i.e. one that does not contain | ||||||||||||
| 2844 | /// DW_OP_LLVM_arg), returns \p Expr converted to variadic form by adding a | ||||||||||||
| 2845 | /// leading [DW_OP_LLVM_arg, 0] to the expression; otherwise returns \p Expr. | ||||||||||||
| 2846 | static const DIExpression * | ||||||||||||
| 2847 | convertToVariadicExpression(const DIExpression *Expr); | ||||||||||||
| 2848 | |||||||||||||
| 2849 | /// If \p Expr is a valid single-location expression, i.e. it refers to only a | ||||||||||||
| 2850 | /// single debug operand at the start of the expression, then return that | ||||||||||||
| 2851 | /// expression in a non-variadic form by removing DW_OP_LLVM_arg from the | ||||||||||||
| 2852 | /// expression if it is present; otherwise returns std::nullopt. | ||||||||||||
| 2853 | static std::optional<const DIExpression *> | ||||||||||||
| 2854 | convertToNonVariadicExpression(const DIExpression *Expr); | ||||||||||||
| 2855 | |||||||||||||
| 2856 | /// Inserts the elements of \p Expr into \p Ops modified to a canonical form, | ||||||||||||
| 2857 | /// which uses DW_OP_LLVM_arg (i.e. is a variadic expression) and folds the | ||||||||||||
| 2858 | /// implied derefence from the \p IsIndirect flag into the expression. This | ||||||||||||
| 2859 | /// allows us to check equivalence between expressions with differing | ||||||||||||
| 2860 | /// directness or variadicness. | ||||||||||||
| 2861 | static void canonicalizeExpressionOps(SmallVectorImpl<uint64_t> &Ops, | ||||||||||||
| 2862 | const DIExpression *Expr, | ||||||||||||
| 2863 | bool IsIndirect); | ||||||||||||
| 2864 | |||||||||||||
| 2865 | /// Determines whether two debug values should produce equivalent DWARF | ||||||||||||
| 2866 | /// expressions, using their DIExpressions and directness, ignoring the | ||||||||||||
| 2867 | /// differences between otherwise identical expressions in variadic and | ||||||||||||
| 2868 | /// non-variadic form and not considering the debug operands. | ||||||||||||
| 2869 | /// \p FirstExpr is the DIExpression for the first debug value. | ||||||||||||
| 2870 | /// \p FirstIndirect should be true if the first debug value is indirect; in | ||||||||||||
| 2871 | /// IR this should be true for dbg.declare intrinsics and false for | ||||||||||||
| 2872 | /// dbg.values, and in MIR this should be true only for DBG_VALUE instructions | ||||||||||||
| 2873 | /// whose second operand is an immediate value. | ||||||||||||
| 2874 | /// \p SecondExpr and \p SecondIndirect have the same meaning as the prior | ||||||||||||
| 2875 | /// arguments, but apply to the second debug value. | ||||||||||||
| 2876 | static bool isEqualExpression(const DIExpression *FirstExpr, | ||||||||||||
| 2877 | bool FirstIndirect, | ||||||||||||
| 2878 | const DIExpression *SecondExpr, | ||||||||||||
| 2879 | bool SecondIndirect); | ||||||||||||
| 2880 | |||||||||||||
| 2881 | /// Append \p Ops with operations to apply the \p Offset. | ||||||||||||
| 2882 | static void appendOffset(SmallVectorImpl<uint64_t> &Ops, int64_t Offset); | ||||||||||||
| 2883 | |||||||||||||
| 2884 | /// If this is a constant offset, extract it. If there is no expression, | ||||||||||||
| 2885 | /// return true with an offset of zero. | ||||||||||||
| 2886 | bool extractIfOffset(int64_t &Offset) const; | ||||||||||||
| 2887 | |||||||||||||
| 2888 | /// Returns true iff this DIExpression contains at least one instance of | ||||||||||||
| 2889 | /// `DW_OP_LLVM_arg, n` for all n in [0, N). | ||||||||||||
| 2890 | bool hasAllLocationOps(unsigned N) const; | ||||||||||||
| 2891 | |||||||||||||
| 2892 | /// Checks if the last 4 elements of the expression are DW_OP_constu <DWARF | ||||||||||||
| 2893 | /// Address Space> DW_OP_swap DW_OP_xderef and extracts the <DWARF Address | ||||||||||||
| 2894 | /// Space>. | ||||||||||||
| 2895 | static const DIExpression *extractAddressClass(const DIExpression *Expr, | ||||||||||||
| 2896 | unsigned &AddrClass); | ||||||||||||
| 2897 | |||||||||||||
| 2898 | /// Used for DIExpression::prepend. | ||||||||||||
| 2899 | enum PrependOps : uint8_t { | ||||||||||||
| 2900 | ApplyOffset = 0, | ||||||||||||
| 2901 | DerefBefore = 1 << 0, | ||||||||||||
| 2902 | DerefAfter = 1 << 1, | ||||||||||||
| 2903 | StackValue = 1 << 2, | ||||||||||||
| 2904 | EntryValue = 1 << 3 | ||||||||||||
| 2905 | }; | ||||||||||||
| 2906 | |||||||||||||
| 2907 | /// Prepend \p DIExpr with a deref and offset operation and optionally turn it | ||||||||||||
| 2908 | /// into a stack value or/and an entry value. | ||||||||||||
| 2909 | static DIExpression *prepend(const DIExpression *Expr, uint8_t Flags, | ||||||||||||
| 2910 | int64_t Offset = 0); | ||||||||||||
| 2911 | |||||||||||||
| 2912 | /// Prepend \p DIExpr with the given opcodes and optionally turn it into a | ||||||||||||
| 2913 | /// stack value. | ||||||||||||
| 2914 | static DIExpression *prependOpcodes(const DIExpression *Expr, | ||||||||||||
| 2915 | SmallVectorImpl<uint64_t> &Ops, | ||||||||||||
| 2916 | bool StackValue = false, | ||||||||||||
| 2917 | bool EntryValue = false); | ||||||||||||
| 2918 | |||||||||||||
| 2919 | /// Append the opcodes \p Ops to \p DIExpr. Unlike \ref appendToStack, the | ||||||||||||
| 2920 | /// returned expression is a stack value only if \p DIExpr is a stack value. | ||||||||||||
| 2921 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||||||||||
| 2922 | /// the same fragment. | ||||||||||||
| 2923 | static DIExpression *append(const DIExpression *Expr, ArrayRef<uint64_t> Ops); | ||||||||||||
| 2924 | |||||||||||||
| 2925 | /// Convert \p DIExpr into a stack value if it isn't one already by appending | ||||||||||||
| 2926 | /// DW_OP_deref if needed, and appending \p Ops to the resulting expression. | ||||||||||||
| 2927 | /// If \p DIExpr describes a fragment, the returned expression will describe | ||||||||||||
| 2928 | /// the same fragment. | ||||||||||||
| 2929 | static DIExpression *appendToStack(const DIExpression *Expr, | ||||||||||||
| 2930 | ArrayRef<uint64_t> Ops); | ||||||||||||
| 2931 | |||||||||||||
| 2932 | /// Create a copy of \p Expr by appending the given list of \p Ops to each | ||||||||||||
| 2933 | /// instance of the operand `DW_OP_LLVM_arg, \p ArgNo`. This is used to | ||||||||||||
| 2934 | /// modify a specific location used by \p Expr, such as when salvaging that | ||||||||||||
| 2935 | /// location. | ||||||||||||
| 2936 | static DIExpression *appendOpsToArg(const DIExpression *Expr, | ||||||||||||
| 2937 | ArrayRef<uint64_t> Ops, unsigned ArgNo, | ||||||||||||
| 2938 | bool StackValue = false); | ||||||||||||
| 2939 | |||||||||||||
| 2940 | /// Create a copy of \p Expr with each instance of | ||||||||||||
| 2941 | /// `DW_OP_LLVM_arg, \p OldArg` replaced with `DW_OP_LLVM_arg, \p NewArg`, | ||||||||||||
| 2942 | /// and each instance of `DW_OP_LLVM_arg, Arg` with `DW_OP_LLVM_arg, Arg - 1` | ||||||||||||
| 2943 | /// for all Arg > \p OldArg. | ||||||||||||
| 2944 | /// This is used when replacing one of the operands of a debug value list | ||||||||||||
| 2945 | /// with another operand in the same list and deleting the old operand. | ||||||||||||
| 2946 | static DIExpression *replaceArg(const DIExpression *Expr, uint64_t OldArg, | ||||||||||||
| 2947 | uint64_t NewArg); | ||||||||||||
| 2948 | |||||||||||||
| 2949 | /// Create a DIExpression to describe one part of an aggregate variable that | ||||||||||||
| 2950 | /// is fragmented across multiple Values. The DW_OP_LLVM_fragment operation | ||||||||||||
| 2951 | /// will be appended to the elements of \c Expr. If \c Expr already contains | ||||||||||||
| 2952 | /// a \c DW_OP_LLVM_fragment \c OffsetInBits is interpreted as an offset | ||||||||||||
| 2953 | /// into the existing fragment. | ||||||||||||
| 2954 | /// | ||||||||||||
| 2955 | /// \param OffsetInBits Offset of the piece in bits. | ||||||||||||
| 2956 | /// \param SizeInBits Size of the piece in bits. | ||||||||||||
| 2957 | /// \return Creating a fragment expression may fail if \c Expr | ||||||||||||
| 2958 | /// contains arithmetic operations that would be | ||||||||||||
| 2959 | /// truncated. | ||||||||||||
| 2960 | static std::optional<DIExpression *> | ||||||||||||
| 2961 | createFragmentExpression(const DIExpression *Expr, unsigned OffsetInBits, | ||||||||||||
| 2962 | unsigned SizeInBits); | ||||||||||||
| 2963 | |||||||||||||
| 2964 | /// Determine the relative position of the fragments passed in. | ||||||||||||
| 2965 | /// Returns -1 if this is entirely before Other, 0 if this and Other overlap, | ||||||||||||
| 2966 | /// 1 if this is entirely after Other. | ||||||||||||
| 2967 | static int fragmentCmp(const FragmentInfo &A, const FragmentInfo &B) { | ||||||||||||
| 2968 | uint64_t l1 = A.OffsetInBits; | ||||||||||||
| 2969 | uint64_t l2 = B.OffsetInBits; | ||||||||||||
| 2970 | uint64_t r1 = l1 + A.SizeInBits; | ||||||||||||
| 2971 | uint64_t r2 = l2 + B.SizeInBits; | ||||||||||||
| 2972 | if (r1 <= l2) | ||||||||||||
| 2973 | return -1; | ||||||||||||
| 2974 | else if (r2 <= l1) | ||||||||||||
| 2975 | return 1; | ||||||||||||
| 2976 | else | ||||||||||||
| 2977 | return 0; | ||||||||||||
| 2978 | } | ||||||||||||
| 2979 | |||||||||||||
| 2980 | using ExtOps = std::array<uint64_t, 6>; | ||||||||||||
| 2981 | |||||||||||||
| 2982 | /// Returns the ops for a zero- or sign-extension in a DIExpression. | ||||||||||||
| 2983 | static ExtOps getExtOps(unsigned FromSize, unsigned ToSize, bool Signed); | ||||||||||||
| 2984 | |||||||||||||
| 2985 | /// Append a zero- or sign-extension to \p Expr. Converts the expression to a | ||||||||||||
| 2986 | /// stack value if it isn't one already. | ||||||||||||
| 2987 | static DIExpression *appendExt(const DIExpression *Expr, unsigned FromSize, | ||||||||||||
| 2988 | unsigned ToSize, bool Signed); | ||||||||||||
| 2989 | |||||||||||||
| 2990 | /// Check if fragments overlap between a pair of FragmentInfos. | ||||||||||||
| 2991 | static bool fragmentsOverlap(const FragmentInfo &A, const FragmentInfo &B) { | ||||||||||||
| 2992 | return fragmentCmp(A, B) == 0; | ||||||||||||
| 2993 | } | ||||||||||||
| 2994 | |||||||||||||
| 2995 | /// Determine the relative position of the fragments described by this | ||||||||||||
| 2996 | /// DIExpression and \p Other. Calls static fragmentCmp implementation. | ||||||||||||
| 2997 | int fragmentCmp(const DIExpression *Other) const { | ||||||||||||
| 2998 | auto Fragment1 = *getFragmentInfo(); | ||||||||||||
| 2999 | auto Fragment2 = *Other->getFragmentInfo(); | ||||||||||||
| 3000 | return fragmentCmp(Fragment1, Fragment2); | ||||||||||||
| 3001 | } | ||||||||||||
| 3002 | |||||||||||||
| 3003 | /// Check if fragments overlap between this DIExpression and \p Other. | ||||||||||||
| 3004 | bool fragmentsOverlap(const DIExpression *Other) const { | ||||||||||||
| 3005 | if (!isFragment() || !Other->isFragment()) | ||||||||||||
| 3006 | return true; | ||||||||||||
| 3007 | return fragmentCmp(Other) == 0; | ||||||||||||
| 3008 | } | ||||||||||||
| 3009 | |||||||||||||
| 3010 | /// Check if the expression consists of exactly one entry value operand. | ||||||||||||
| 3011 | /// (This is the only configuration of entry values that is supported.) | ||||||||||||
| 3012 | bool isEntryValue() const; | ||||||||||||
| 3013 | |||||||||||||
| 3014 | /// Try to shorten an expression with an initial constant operand. | ||||||||||||
| 3015 | /// Returns a new expression and constant on success, or the original | ||||||||||||
| 3016 | /// expression and constant on failure. | ||||||||||||
| 3017 | std::pair<DIExpression *, const ConstantInt *> | ||||||||||||
| 3018 | constantFold(const ConstantInt *CI); | ||||||||||||
| 3019 | }; | ||||||||||||
| 3020 | |||||||||||||
| 3021 | inline bool operator==(const DIExpression::FragmentInfo &A, | ||||||||||||
| 3022 | const DIExpression::FragmentInfo &B) { | ||||||||||||
| 3023 | return std::tie(A.SizeInBits, A.OffsetInBits) == | ||||||||||||
| 3024 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||||||||||
| 3025 | } | ||||||||||||
| 3026 | |||||||||||||
| 3027 | inline bool operator<(const DIExpression::FragmentInfo &A, | ||||||||||||
| 3028 | const DIExpression::FragmentInfo &B) { | ||||||||||||
| 3029 | return std::tie(A.SizeInBits, A.OffsetInBits) < | ||||||||||||
| 3030 | std::tie(B.SizeInBits, B.OffsetInBits); | ||||||||||||
| 3031 | } | ||||||||||||
| 3032 | |||||||||||||
| 3033 | template <> struct DenseMapInfo<DIExpression::FragmentInfo> { | ||||||||||||
| 3034 | using FragInfo = DIExpression::FragmentInfo; | ||||||||||||
| 3035 | static const uint64_t MaxVal = std::numeric_limits<uint64_t>::max(); | ||||||||||||
| 3036 | |||||||||||||
| 3037 | static inline FragInfo getEmptyKey() { return {MaxVal, MaxVal}; } | ||||||||||||
| 3038 | |||||||||||||
| 3039 | static inline FragInfo getTombstoneKey() { return {MaxVal - 1, MaxVal - 1}; } | ||||||||||||
| 3040 | |||||||||||||
| 3041 | static unsigned getHashValue(const FragInfo &Frag) { | ||||||||||||
| 3042 | return (Frag.SizeInBits & 0xffff) << 16 | (Frag.OffsetInBits & 0xffff); | ||||||||||||
| 3043 | } | ||||||||||||
| 3044 | |||||||||||||
| 3045 | static bool isEqual(const FragInfo &A, const FragInfo &B) { return A == B; } | ||||||||||||
| 3046 | }; | ||||||||||||
| 3047 | |||||||||||||
| 3048 | /// Global variables. | ||||||||||||
| 3049 | /// | ||||||||||||
| 3050 | /// TODO: Remove DisplayName. It's always equal to Name. | ||||||||||||
| 3051 | class DIGlobalVariable : public DIVariable { | ||||||||||||
| 3052 | friend class LLVMContextImpl; | ||||||||||||
| 3053 | friend class MDNode; | ||||||||||||
| 3054 | |||||||||||||
| 3055 | bool IsLocalToUnit; | ||||||||||||
| 3056 | bool IsDefinition; | ||||||||||||
| 3057 | |||||||||||||
| 3058 | DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 3059 | bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, | ||||||||||||
| 3060 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 3061 | : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), | ||||||||||||
| 3062 | IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} | ||||||||||||
| 3063 | ~DIGlobalVariable() = default; | ||||||||||||
| 3064 | |||||||||||||
| 3065 | static DIGlobalVariable * | ||||||||||||
| 3066 | getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
| 3067 | StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, | ||||||||||||
| 3068 | bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
| 3069 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||||||||||
| 3070 | uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, | ||||||||||||
| 3071 | bool ShouldCreate = true) { | ||||||||||||
| 3072 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), | ||||||||||||
| 3073 | getCanonicalMDString(Context, LinkageName), File, Line, Type, | ||||||||||||
| 3074 | IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, | ||||||||||||
| 3075 | cast_or_null<Metadata>(TemplateParams), AlignInBits, | ||||||||||||
| 3076 | Annotations.get(), Storage, ShouldCreate); | ||||||||||||
| 3077 | } | ||||||||||||
| 3078 | static DIGlobalVariable * | ||||||||||||
| 3079 | getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
| 3080 | MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, | ||||||||||||
| 3081 | bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
| 3082 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||||||||||
| 3083 | uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, | ||||||||||||
| 3084 | bool ShouldCreate = true); | ||||||||||||
| 3085 | |||||||||||||
| 3086 | TempDIGlobalVariable cloneImpl() const { | ||||||||||||
| 3087 | return getTemporary(getContext(), getScope(), getName(), getLinkageName(), | ||||||||||||
| 3088 | getFile(), getLine(), getType(), isLocalToUnit(), | ||||||||||||
| 3089 | isDefinition(), getStaticDataMemberDeclaration(), | ||||||||||||
| 3090 | getTemplateParams(), getAlignInBits(), | ||||||||||||
| 3091 | getAnnotations()); | ||||||||||||
| 3092 | } | ||||||||||||
| 3093 | |||||||||||||
| 3094 | public: | ||||||||||||
| 3095 | DEFINE_MDNODE_GET( | ||||||||||||
| 3096 | DIGlobalVariable, | ||||||||||||
| 3097 | (DIScope * Scope, StringRef Name, StringRef LinkageName, DIFile *File, | ||||||||||||
| 3098 | unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
| 3099 | DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, | ||||||||||||
| 3100 | uint32_t AlignInBits, DINodeArray Annotations), | ||||||||||||
| 3101 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, | ||||||||||||
| 3102 | StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) | ||||||||||||
| 3103 | DEFINE_MDNODE_GET( | ||||||||||||
| 3104 | DIGlobalVariable, | ||||||||||||
| 3105 | (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, | ||||||||||||
| 3106 | unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, | ||||||||||||
| 3107 | Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, | ||||||||||||
| 3108 | uint32_t AlignInBits, Metadata *Annotations), | ||||||||||||
| 3109 | (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, | ||||||||||||
| 3110 | StaticDataMemberDeclaration, TemplateParams, AlignInBits, Annotations)) | ||||||||||||
| 3111 | |||||||||||||
| 3112 | TempDIGlobalVariable clone() const { return cloneImpl(); } | ||||||||||||
| 3113 | |||||||||||||
| 3114 | bool isLocalToUnit() const { return IsLocalToUnit; } | ||||||||||||
| 3115 | bool isDefinition() const { return IsDefinition; } | ||||||||||||
| 3116 | StringRef getDisplayName() const { return getStringOperand(4); } | ||||||||||||
| 3117 | StringRef getLinkageName() const { return getStringOperand(5); } | ||||||||||||
| 3118 | DIDerivedType *getStaticDataMemberDeclaration() const { | ||||||||||||
| 3119 | return cast_or_null<DIDerivedType>(getRawStaticDataMemberDeclaration()); | ||||||||||||
| 3120 | } | ||||||||||||
| 3121 | DINodeArray getAnnotations() const { | ||||||||||||
| 3122 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
| 3123 | } | ||||||||||||
| 3124 | |||||||||||||
| 3125 | MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } | ||||||||||||
| 3126 | Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } | ||||||||||||
| 3127 | Metadata *getRawTemplateParams() const { return getOperand(7); } | ||||||||||||
| 3128 | MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); } | ||||||||||||
| 3129 | Metadata *getRawAnnotations() const { return getOperand(8); } | ||||||||||||
| 3130 | |||||||||||||
| 3131 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3132 | return MD->getMetadataID() == DIGlobalVariableKind; | ||||||||||||
| 3133 | } | ||||||||||||
| 3134 | }; | ||||||||||||
| 3135 | |||||||||||||
| 3136 | class DICommonBlock : public DIScope { | ||||||||||||
| 3137 | unsigned LineNo; | ||||||||||||
| 3138 | |||||||||||||
| 3139 | friend class LLVMContextImpl; | ||||||||||||
| 3140 | friend class MDNode; | ||||||||||||
| 3141 | |||||||||||||
| 3142 | DICommonBlock(LLVMContext &Context, StorageType Storage, unsigned LineNo, | ||||||||||||
| 3143 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 3144 | |||||||||||||
| 3145 | static DICommonBlock *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
| 3146 | DIGlobalVariable *Decl, StringRef Name, | ||||||||||||
| 3147 | DIFile *File, unsigned LineNo, | ||||||||||||
| 3148 | StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 3149 | return getImpl(Context, Scope, Decl, getCanonicalMDString(Context, Name), | ||||||||||||
| 3150 | File, LineNo, Storage, ShouldCreate); | ||||||||||||
| 3151 | } | ||||||||||||
| 3152 | static DICommonBlock *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
| 3153 | Metadata *Decl, MDString *Name, Metadata *File, | ||||||||||||
| 3154 | unsigned LineNo, StorageType Storage, | ||||||||||||
| 3155 | bool ShouldCreate = true); | ||||||||||||
| 3156 | |||||||||||||
| 3157 | TempDICommonBlock cloneImpl() const { | ||||||||||||
| 3158 | return getTemporary(getContext(), getScope(), getDecl(), getName(), | ||||||||||||
| 3159 | getFile(), getLineNo()); | ||||||||||||
| 3160 | } | ||||||||||||
| 3161 | |||||||||||||
| 3162 | public: | ||||||||||||
| 3163 | DEFINE_MDNODE_GET(DICommonBlock, | ||||||||||||
| 3164 | (DIScope * Scope, DIGlobalVariable *Decl, StringRef Name, | ||||||||||||
| 3165 | DIFile *File, unsigned LineNo), | ||||||||||||
| 3166 | (Scope, Decl, Name, File, LineNo)) | ||||||||||||
| 3167 | DEFINE_MDNODE_GET(DICommonBlock, | ||||||||||||
| 3168 | (Metadata * Scope, Metadata *Decl, MDString *Name, | ||||||||||||
| 3169 | Metadata *File, unsigned LineNo), | ||||||||||||
| 3170 | (Scope, Decl, Name, File, LineNo)) | ||||||||||||
| 3171 | |||||||||||||
| 3172 | TempDICommonBlock clone() const { return cloneImpl(); } | ||||||||||||
| 3173 | |||||||||||||
| 3174 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 3175 | DIGlobalVariable *getDecl() const { | ||||||||||||
| 3176 | return cast_or_null<DIGlobalVariable>(getRawDecl()); | ||||||||||||
| 3177 | } | ||||||||||||
| 3178 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 3179 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 3180 | unsigned getLineNo() const { return LineNo; } | ||||||||||||
| 3181 | |||||||||||||
| 3182 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
| 3183 | Metadata *getRawDecl() const { return getOperand(1); } | ||||||||||||
| 3184 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 3185 | Metadata *getRawFile() const { return getOperand(3); } | ||||||||||||
| 3186 | |||||||||||||
| 3187 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3188 | return MD->getMetadataID() == DICommonBlockKind; | ||||||||||||
| 3189 | } | ||||||||||||
| 3190 | }; | ||||||||||||
| 3191 | |||||||||||||
| 3192 | /// Local variable. | ||||||||||||
| 3193 | /// | ||||||||||||
| 3194 | /// TODO: Split up flags. | ||||||||||||
| 3195 | class DILocalVariable : public DIVariable { | ||||||||||||
| 3196 | friend class LLVMContextImpl; | ||||||||||||
| 3197 | friend class MDNode; | ||||||||||||
| 3198 | |||||||||||||
| 3199 | unsigned Arg : 16; | ||||||||||||
| 3200 | DIFlags Flags; | ||||||||||||
| 3201 | |||||||||||||
| 3202 | DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 3203 | unsigned Arg, DIFlags Flags, uint32_t AlignInBits, | ||||||||||||
| 3204 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 3205 | : DIVariable(C, DILocalVariableKind, Storage, Line, Ops, AlignInBits), | ||||||||||||
| 3206 | Arg(Arg), Flags(Flags) { | ||||||||||||
| 3207 | assert(Arg < (1 << 16) && "DILocalVariable: Arg out of range")(static_cast <bool> (Arg < (1 << 16) && "DILocalVariable: Arg out of range") ? void (0) : __assert_fail ("Arg < (1 << 16) && \"DILocalVariable: Arg out of range\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3207, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 3208 | } | ||||||||||||
| 3209 | ~DILocalVariable() = default; | ||||||||||||
| 3210 | |||||||||||||
| 3211 | static DILocalVariable *getImpl(LLVMContext &Context, DIScope *Scope, | ||||||||||||
| 3212 | StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
| 3213 | DIType *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
| 3214 | uint32_t AlignInBits, DINodeArray Annotations, | ||||||||||||
| 3215 | StorageType Storage, | ||||||||||||
| 3216 | bool ShouldCreate = true) { | ||||||||||||
| 3217 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||||||||||
| 3218 | Line, Type, Arg, Flags, AlignInBits, Annotations.get(), | ||||||||||||
| 3219 | Storage, ShouldCreate); | ||||||||||||
| 3220 | } | ||||||||||||
| 3221 | static DILocalVariable *getImpl(LLVMContext &Context, Metadata *Scope, | ||||||||||||
| 3222 | MDString *Name, Metadata *File, unsigned Line, | ||||||||||||
| 3223 | Metadata *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
| 3224 | uint32_t AlignInBits, Metadata *Annotations, | ||||||||||||
| 3225 | StorageType Storage, | ||||||||||||
| 3226 | bool ShouldCreate = true); | ||||||||||||
| 3227 | |||||||||||||
| 3228 | TempDILocalVariable cloneImpl() const { | ||||||||||||
| 3229 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||||||||||
| 3230 | getLine(), getType(), getArg(), getFlags(), | ||||||||||||
| 3231 | getAlignInBits(), getAnnotations()); | ||||||||||||
| 3232 | } | ||||||||||||
| 3233 | |||||||||||||
| 3234 | public: | ||||||||||||
| 3235 | DEFINE_MDNODE_GET(DILocalVariable, | ||||||||||||
| 3236 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||||||||||
| 3237 | unsigned Line, DIType *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
| 3238 | uint32_t AlignInBits, DINodeArray Annotations), | ||||||||||||
| 3239 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||||||||||
| 3240 | Annotations)) | ||||||||||||
| 3241 | DEFINE_MDNODE_GET(DILocalVariable, | ||||||||||||
| 3242 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||||||||||
| 3243 | unsigned Line, Metadata *Type, unsigned Arg, DIFlags Flags, | ||||||||||||
| 3244 | uint32_t AlignInBits, Metadata *Annotations), | ||||||||||||
| 3245 | (Scope, Name, File, Line, Type, Arg, Flags, AlignInBits, | ||||||||||||
| 3246 | Annotations)) | ||||||||||||
| 3247 | |||||||||||||
| 3248 | TempDILocalVariable clone() const { return cloneImpl(); } | ||||||||||||
| 3249 | |||||||||||||
| 3250 | /// Get the local scope for this variable. | ||||||||||||
| 3251 | /// | ||||||||||||
| 3252 | /// Variables must be defined in a local scope. | ||||||||||||
| 3253 | DILocalScope *getScope() const { | ||||||||||||
| 3254 | return cast<DILocalScope>(DIVariable::getScope()); | ||||||||||||
| 3255 | } | ||||||||||||
| 3256 | |||||||||||||
| 3257 | bool isParameter() const { return Arg; } | ||||||||||||
| 3258 | unsigned getArg() const { return Arg; } | ||||||||||||
| 3259 | DIFlags getFlags() const { return Flags; } | ||||||||||||
| 3260 | |||||||||||||
| 3261 | DINodeArray getAnnotations() const { | ||||||||||||
| 3262 | return cast_or_null<MDTuple>(getRawAnnotations()); | ||||||||||||
| 3263 | } | ||||||||||||
| 3264 | Metadata *getRawAnnotations() const { return getOperand(4); } | ||||||||||||
| 3265 | |||||||||||||
| 3266 | bool isArtificial() const { return getFlags() & FlagArtificial; } | ||||||||||||
| 3267 | bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } | ||||||||||||
| 3268 | |||||||||||||
| 3269 | /// Check that a location is valid for this variable. | ||||||||||||
| 3270 | /// | ||||||||||||
| 3271 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||||||||||
| 3272 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||||||||||
| 3273 | /// to a \a DbgInfoIntrinsic.) | ||||||||||||
| 3274 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||||||||||
| 3275 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||||||||||
| 3276 | } | ||||||||||||
| 3277 | |||||||||||||
| 3278 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3279 | return MD->getMetadataID() == DILocalVariableKind; | ||||||||||||
| 3280 | } | ||||||||||||
| 3281 | }; | ||||||||||||
| 3282 | |||||||||||||
| 3283 | /// Label. | ||||||||||||
| 3284 | /// | ||||||||||||
| 3285 | class DILabel : public DINode { | ||||||||||||
| 3286 | friend class LLVMContextImpl; | ||||||||||||
| 3287 | friend class MDNode; | ||||||||||||
| 3288 | |||||||||||||
| 3289 | unsigned Line; | ||||||||||||
| 3290 | |||||||||||||
| 3291 | DILabel(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 3292 | ArrayRef<Metadata *> Ops); | ||||||||||||
| 3293 | ~DILabel() = default; | ||||||||||||
| 3294 | |||||||||||||
| 3295 | static DILabel *getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, | ||||||||||||
| 3296 | DIFile *File, unsigned Line, StorageType Storage, | ||||||||||||
| 3297 | bool ShouldCreate = true) { | ||||||||||||
| 3298 | return getImpl(Context, Scope, getCanonicalMDString(Context, Name), File, | ||||||||||||
| 3299 | Line, Storage, ShouldCreate); | ||||||||||||
| 3300 | } | ||||||||||||
| 3301 | static DILabel *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, | ||||||||||||
| 3302 | Metadata *File, unsigned Line, StorageType Storage, | ||||||||||||
| 3303 | bool ShouldCreate = true); | ||||||||||||
| 3304 | |||||||||||||
| 3305 | TempDILabel cloneImpl() const { | ||||||||||||
| 3306 | return getTemporary(getContext(), getScope(), getName(), getFile(), | ||||||||||||
| 3307 | getLine()); | ||||||||||||
| 3308 | } | ||||||||||||
| 3309 | |||||||||||||
| 3310 | public: | ||||||||||||
| 3311 | DEFINE_MDNODE_GET(DILabel, | ||||||||||||
| 3312 | (DILocalScope * Scope, StringRef Name, DIFile *File, | ||||||||||||
| 3313 | unsigned Line), | ||||||||||||
| 3314 | (Scope, Name, File, Line)) | ||||||||||||
| 3315 | DEFINE_MDNODE_GET(DILabel, | ||||||||||||
| 3316 | (Metadata * Scope, MDString *Name, Metadata *File, | ||||||||||||
| 3317 | unsigned Line), | ||||||||||||
| 3318 | (Scope, Name, File, Line)) | ||||||||||||
| 3319 | |||||||||||||
| 3320 | TempDILabel clone() const { return cloneImpl(); } | ||||||||||||
| 3321 | |||||||||||||
| 3322 | /// Get the local scope for this label. | ||||||||||||
| 3323 | /// | ||||||||||||
| 3324 | /// Labels must be defined in a local scope. | ||||||||||||
| 3325 | DILocalScope *getScope() const { | ||||||||||||
| 3326 | return cast_or_null<DILocalScope>(getRawScope()); | ||||||||||||
| 3327 | } | ||||||||||||
| 3328 | unsigned getLine() const { return Line; } | ||||||||||||
| 3329 | StringRef getName() const { return getStringOperand(1); } | ||||||||||||
| 3330 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 3331 | |||||||||||||
| 3332 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
| 3333 | MDString *getRawName() const { return getOperandAs<MDString>(1); } | ||||||||||||
| 3334 | Metadata *getRawFile() const { return getOperand(2); } | ||||||||||||
| 3335 | |||||||||||||
| 3336 | /// Check that a location is valid for this label. | ||||||||||||
| 3337 | /// | ||||||||||||
| 3338 | /// Check that \c DL exists, is in the same subprogram, and has the same | ||||||||||||
| 3339 | /// inlined-at location as \c this. (Otherwise, it's not a valid attachment | ||||||||||||
| 3340 | /// to a \a DbgInfoIntrinsic.) | ||||||||||||
| 3341 | bool isValidLocationForIntrinsic(const DILocation *DL) const { | ||||||||||||
| 3342 | return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); | ||||||||||||
| 3343 | } | ||||||||||||
| 3344 | |||||||||||||
| 3345 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3346 | return MD->getMetadataID() == DILabelKind; | ||||||||||||
| 3347 | } | ||||||||||||
| 3348 | }; | ||||||||||||
| 3349 | |||||||||||||
| 3350 | class DIObjCProperty : public DINode { | ||||||||||||
| 3351 | friend class LLVMContextImpl; | ||||||||||||
| 3352 | friend class MDNode; | ||||||||||||
| 3353 | |||||||||||||
| 3354 | unsigned Line; | ||||||||||||
| 3355 | unsigned Attributes; | ||||||||||||
| 3356 | |||||||||||||
| 3357 | DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, | ||||||||||||
| 3358 | unsigned Attributes, ArrayRef<Metadata *> Ops); | ||||||||||||
| 3359 | ~DIObjCProperty() = default; | ||||||||||||
| 3360 | |||||||||||||
| 3361 | static DIObjCProperty * | ||||||||||||
| 3362 | getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
| 3363 | StringRef GetterName, StringRef SetterName, unsigned Attributes, | ||||||||||||
| 3364 | DIType *Type, StorageType Storage, bool ShouldCreate = true) { | ||||||||||||
| 3365 | return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, | ||||||||||||
| 3366 | getCanonicalMDString(Context, GetterName), | ||||||||||||
| 3367 | getCanonicalMDString(Context, SetterName), Attributes, Type, | ||||||||||||
| 3368 | Storage, ShouldCreate); | ||||||||||||
| 3369 | } | ||||||||||||
| 3370 | static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, | ||||||||||||
| 3371 | Metadata *File, unsigned Line, | ||||||||||||
| 3372 | MDString *GetterName, MDString *SetterName, | ||||||||||||
| 3373 | unsigned Attributes, Metadata *Type, | ||||||||||||
| 3374 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 3375 | |||||||||||||
| 3376 | TempDIObjCProperty cloneImpl() const { | ||||||||||||
| 3377 | return getTemporary(getContext(), getName(), getFile(), getLine(), | ||||||||||||
| 3378 | getGetterName(), getSetterName(), getAttributes(), | ||||||||||||
| 3379 | getType()); | ||||||||||||
| 3380 | } | ||||||||||||
| 3381 | |||||||||||||
| 3382 | public: | ||||||||||||
| 3383 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||||||||||
| 3384 | (StringRef Name, DIFile *File, unsigned Line, | ||||||||||||
| 3385 | StringRef GetterName, StringRef SetterName, | ||||||||||||
| 3386 | unsigned Attributes, DIType *Type), | ||||||||||||
| 3387 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||||||||||
| 3388 | Type)) | ||||||||||||
| 3389 | DEFINE_MDNODE_GET(DIObjCProperty, | ||||||||||||
| 3390 | (MDString * Name, Metadata *File, unsigned Line, | ||||||||||||
| 3391 | MDString *GetterName, MDString *SetterName, | ||||||||||||
| 3392 | unsigned Attributes, Metadata *Type), | ||||||||||||
| 3393 | (Name, File, Line, GetterName, SetterName, Attributes, | ||||||||||||
| 3394 | Type)) | ||||||||||||
| 3395 | |||||||||||||
| 3396 | TempDIObjCProperty clone() const { return cloneImpl(); } | ||||||||||||
| 3397 | |||||||||||||
| 3398 | unsigned getLine() const { return Line; } | ||||||||||||
| 3399 | unsigned getAttributes() const { return Attributes; } | ||||||||||||
| 3400 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
| 3401 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 3402 | StringRef getGetterName() const { return getStringOperand(2); } | ||||||||||||
| 3403 | StringRef getSetterName() const { return getStringOperand(3); } | ||||||||||||
| 3404 | DIType *getType() const { return cast_or_null<DIType>(getRawType()); } | ||||||||||||
| 3405 | |||||||||||||
| 3406 | StringRef getFilename() const { | ||||||||||||
| 3407 | if (auto *F = getFile()) | ||||||||||||
| 3408 | return F->getFilename(); | ||||||||||||
| 3409 | return ""; | ||||||||||||
| 3410 | } | ||||||||||||
| 3411 | |||||||||||||
| 3412 | StringRef getDirectory() const { | ||||||||||||
| 3413 | if (auto *F = getFile()) | ||||||||||||
| 3414 | return F->getDirectory(); | ||||||||||||
| 3415 | return ""; | ||||||||||||
| 3416 | } | ||||||||||||
| 3417 | |||||||||||||
| 3418 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 3419 | Metadata *getRawFile() const { return getOperand(1); } | ||||||||||||
| 3420 | MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 3421 | MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } | ||||||||||||
| 3422 | Metadata *getRawType() const { return getOperand(4); } | ||||||||||||
| 3423 | |||||||||||||
| 3424 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3425 | return MD->getMetadataID() == DIObjCPropertyKind; | ||||||||||||
| 3426 | } | ||||||||||||
| 3427 | }; | ||||||||||||
| 3428 | |||||||||||||
| 3429 | /// An imported module (C++ using directive or similar). | ||||||||||||
| 3430 | class DIImportedEntity : public DINode { | ||||||||||||
| 3431 | friend class LLVMContextImpl; | ||||||||||||
| 3432 | friend class MDNode; | ||||||||||||
| 3433 | |||||||||||||
| 3434 | unsigned Line; | ||||||||||||
| 3435 | |||||||||||||
| 3436 | DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, | ||||||||||||
| 3437 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||||||||||
| 3438 | : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} | ||||||||||||
| 3439 | ~DIImportedEntity() = default; | ||||||||||||
| 3440 | |||||||||||||
| 3441 | static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, | ||||||||||||
| 3442 | DIScope *Scope, DINode *Entity, DIFile *File, | ||||||||||||
| 3443 | unsigned Line, StringRef Name, | ||||||||||||
| 3444 | DINodeArray Elements, StorageType Storage, | ||||||||||||
| 3445 | bool ShouldCreate = true) { | ||||||||||||
| 3446 | return getImpl(Context, Tag, Scope, Entity, File, Line, | ||||||||||||
| 3447 | getCanonicalMDString(Context, Name), Elements.get(), Storage, | ||||||||||||
| 3448 | ShouldCreate); | ||||||||||||
| 3449 | } | ||||||||||||
| 3450 | static DIImportedEntity * | ||||||||||||
| 3451 | getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||||||||||
| 3452 | Metadata *File, unsigned Line, MDString *Name, Metadata *Elements, | ||||||||||||
| 3453 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 3454 | |||||||||||||
| 3455 | TempDIImportedEntity cloneImpl() const { | ||||||||||||
| 3456 | return getTemporary(getContext(), getTag(), getScope(), getEntity(), | ||||||||||||
| 3457 | getFile(), getLine(), getName(), getElements()); | ||||||||||||
| 3458 | } | ||||||||||||
| 3459 | |||||||||||||
| 3460 | public: | ||||||||||||
| 3461 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||||||||||
| 3462 | (unsigned Tag, DIScope *Scope, DINode *Entity, DIFile *File, | ||||||||||||
| 3463 | unsigned Line, StringRef Name = "", | ||||||||||||
| 3464 | DINodeArray Elements = nullptr), | ||||||||||||
| 3465 | (Tag, Scope, Entity, File, Line, Name, Elements)) | ||||||||||||
| 3466 | DEFINE_MDNODE_GET(DIImportedEntity, | ||||||||||||
| 3467 | (unsigned Tag, Metadata *Scope, Metadata *Entity, | ||||||||||||
| 3468 | Metadata *File, unsigned Line, MDString *Name, | ||||||||||||
| 3469 | Metadata *Elements = nullptr), | ||||||||||||
| 3470 | (Tag, Scope, Entity, File, Line, Name, Elements)) | ||||||||||||
| 3471 | |||||||||||||
| 3472 | TempDIImportedEntity clone() const { return cloneImpl(); } | ||||||||||||
| 3473 | |||||||||||||
| 3474 | unsigned getLine() const { return Line; } | ||||||||||||
| 3475 | DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } | ||||||||||||
| 3476 | DINode *getEntity() const { return cast_or_null<DINode>(getRawEntity()); } | ||||||||||||
| 3477 | StringRef getName() const { return getStringOperand(2); } | ||||||||||||
| 3478 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 3479 | DINodeArray getElements() const { | ||||||||||||
| 3480 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
| 3481 | } | ||||||||||||
| 3482 | |||||||||||||
| 3483 | Metadata *getRawScope() const { return getOperand(0); } | ||||||||||||
| 3484 | Metadata *getRawEntity() const { return getOperand(1); } | ||||||||||||
| 3485 | MDString *getRawName() const { return getOperandAs<MDString>(2); } | ||||||||||||
| 3486 | Metadata *getRawFile() const { return getOperand(3); } | ||||||||||||
| 3487 | Metadata *getRawElements() const { return getOperand(4); } | ||||||||||||
| 3488 | |||||||||||||
| 3489 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3490 | return MD->getMetadataID() == DIImportedEntityKind; | ||||||||||||
| 3491 | } | ||||||||||||
| 3492 | }; | ||||||||||||
| 3493 | |||||||||||||
| 3494 | /// A pair of DIGlobalVariable and DIExpression. | ||||||||||||
| 3495 | class DIGlobalVariableExpression : public MDNode { | ||||||||||||
| 3496 | friend class LLVMContextImpl; | ||||||||||||
| 3497 | friend class MDNode; | ||||||||||||
| 3498 | |||||||||||||
| 3499 | DIGlobalVariableExpression(LLVMContext &C, StorageType Storage, | ||||||||||||
| 3500 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 3501 | : MDNode(C, DIGlobalVariableExpressionKind, Storage, Ops) {} | ||||||||||||
| 3502 | ~DIGlobalVariableExpression() = default; | ||||||||||||
| 3503 | |||||||||||||
| 3504 | static DIGlobalVariableExpression * | ||||||||||||
| 3505 | getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Expression, | ||||||||||||
| 3506 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 3507 | |||||||||||||
| 3508 | TempDIGlobalVariableExpression cloneImpl() const { | ||||||||||||
| 3509 | return getTemporary(getContext(), getVariable(), getExpression()); | ||||||||||||
| 3510 | } | ||||||||||||
| 3511 | |||||||||||||
| 3512 | public: | ||||||||||||
| 3513 | DEFINE_MDNODE_GET(DIGlobalVariableExpression, | ||||||||||||
| 3514 | (Metadata * Variable, Metadata *Expression), | ||||||||||||
| 3515 | (Variable, Expression)) | ||||||||||||
| 3516 | |||||||||||||
| 3517 | TempDIGlobalVariableExpression clone() const { return cloneImpl(); } | ||||||||||||
| 3518 | |||||||||||||
| 3519 | Metadata *getRawVariable() const { return getOperand(0); } | ||||||||||||
| 3520 | |||||||||||||
| 3521 | DIGlobalVariable *getVariable() const { | ||||||||||||
| 3522 | return cast_or_null<DIGlobalVariable>(getRawVariable()); | ||||||||||||
| 3523 | } | ||||||||||||
| 3524 | |||||||||||||
| 3525 | Metadata *getRawExpression() const { return getOperand(1); } | ||||||||||||
| 3526 | |||||||||||||
| 3527 | DIExpression *getExpression() const { | ||||||||||||
| 3528 | return cast<DIExpression>(getRawExpression()); | ||||||||||||
| 3529 | } | ||||||||||||
| 3530 | |||||||||||||
| 3531 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3532 | return MD->getMetadataID() == DIGlobalVariableExpressionKind; | ||||||||||||
| 3533 | } | ||||||||||||
| 3534 | }; | ||||||||||||
| 3535 | |||||||||||||
| 3536 | /// Macro Info DWARF-like metadata node. | ||||||||||||
| 3537 | /// | ||||||||||||
| 3538 | /// A metadata node with a DWARF macro info (i.e., a constant named | ||||||||||||
| 3539 | /// \c DW_MACINFO_*, defined in llvm/BinaryFormat/Dwarf.h). Called \a | ||||||||||||
| 3540 | /// DIMacroNode | ||||||||||||
| 3541 | /// because it's potentially used for non-DWARF output. | ||||||||||||
| 3542 | class DIMacroNode : public MDNode { | ||||||||||||
| 3543 | friend class LLVMContextImpl; | ||||||||||||
| 3544 | friend class MDNode; | ||||||||||||
| 3545 | |||||||||||||
| 3546 | protected: | ||||||||||||
| 3547 | DIMacroNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned MIType, | ||||||||||||
| 3548 | ArrayRef<Metadata *> Ops1, | ||||||||||||
| 3549 | ArrayRef<Metadata *> Ops2 = std::nullopt) | ||||||||||||
| 3550 | : MDNode(C, ID, Storage, Ops1, Ops2) { | ||||||||||||
| 3551 | assert(MIType < 1u << 16)(static_cast <bool> (MIType < 1u << 16) ? void (0) : __assert_fail ("MIType < 1u << 16", "llvm/include/llvm/IR/DebugInfoMetadata.h" , 3551, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 3552 | SubclassData16 = MIType; | ||||||||||||
| 3553 | } | ||||||||||||
| 3554 | ~DIMacroNode() = default; | ||||||||||||
| 3555 | |||||||||||||
| 3556 | template <class Ty> Ty *getOperandAs(unsigned I) const { | ||||||||||||
| 3557 | return cast_or_null<Ty>(getOperand(I)); | ||||||||||||
| 3558 | } | ||||||||||||
| 3559 | |||||||||||||
| 3560 | StringRef getStringOperand(unsigned I) const { | ||||||||||||
| 3561 | if (auto *S = getOperandAs<MDString>(I)) | ||||||||||||
| 3562 | return S->getString(); | ||||||||||||
| 3563 | return StringRef(); | ||||||||||||
| 3564 | } | ||||||||||||
| 3565 | |||||||||||||
| 3566 | static MDString *getCanonicalMDString(LLVMContext &Context, StringRef S) { | ||||||||||||
| 3567 | if (S.empty()) | ||||||||||||
| 3568 | return nullptr; | ||||||||||||
| 3569 | return MDString::get(Context, S); | ||||||||||||
| 3570 | } | ||||||||||||
| 3571 | |||||||||||||
| 3572 | public: | ||||||||||||
| 3573 | unsigned getMacinfoType() const { return SubclassData16; } | ||||||||||||
| 3574 | |||||||||||||
| 3575 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3576 | switch (MD->getMetadataID()) { | ||||||||||||
| 3577 | default: | ||||||||||||
| 3578 | return false; | ||||||||||||
| 3579 | case DIMacroKind: | ||||||||||||
| 3580 | case DIMacroFileKind: | ||||||||||||
| 3581 | return true; | ||||||||||||
| 3582 | } | ||||||||||||
| 3583 | } | ||||||||||||
| 3584 | }; | ||||||||||||
| 3585 | |||||||||||||
| 3586 | class DIMacro : public DIMacroNode { | ||||||||||||
| 3587 | friend class LLVMContextImpl; | ||||||||||||
| 3588 | friend class MDNode; | ||||||||||||
| 3589 | |||||||||||||
| 3590 | unsigned Line; | ||||||||||||
| 3591 | |||||||||||||
| 3592 | DIMacro(LLVMContext &C, StorageType Storage, unsigned MIType, unsigned Line, | ||||||||||||
| 3593 | ArrayRef<Metadata *> Ops) | ||||||||||||
| 3594 | : DIMacroNode(C, DIMacroKind, Storage, MIType, Ops), Line(Line) {} | ||||||||||||
| 3595 | ~DIMacro() = default; | ||||||||||||
| 3596 | |||||||||||||
| 3597 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||||||||||
| 3598 | StringRef Name, StringRef Value, StorageType Storage, | ||||||||||||
| 3599 | bool ShouldCreate = true) { | ||||||||||||
| 3600 | return getImpl(Context, MIType, Line, getCanonicalMDString(Context, Name), | ||||||||||||
| 3601 | getCanonicalMDString(Context, Value), Storage, ShouldCreate); | ||||||||||||
| 3602 | } | ||||||||||||
| 3603 | static DIMacro *getImpl(LLVMContext &Context, unsigned MIType, unsigned Line, | ||||||||||||
| 3604 | MDString *Name, MDString *Value, StorageType Storage, | ||||||||||||
| 3605 | bool ShouldCreate = true); | ||||||||||||
| 3606 | |||||||||||||
| 3607 | TempDIMacro cloneImpl() const { | ||||||||||||
| 3608 | return getTemporary(getContext(), getMacinfoType(), getLine(), getName(), | ||||||||||||
| 3609 | getValue()); | ||||||||||||
| 3610 | } | ||||||||||||
| 3611 | |||||||||||||
| 3612 | public: | ||||||||||||
| 3613 | DEFINE_MDNODE_GET(DIMacro, | ||||||||||||
| 3614 | (unsigned MIType, unsigned Line, StringRef Name, | ||||||||||||
| 3615 | StringRef Value = ""), | ||||||||||||
| 3616 | (MIType, Line, Name, Value)) | ||||||||||||
| 3617 | DEFINE_MDNODE_GET(DIMacro, | ||||||||||||
| 3618 | (unsigned MIType, unsigned Line, MDString *Name, | ||||||||||||
| 3619 | MDString *Value), | ||||||||||||
| 3620 | (MIType, Line, Name, Value)) | ||||||||||||
| 3621 | |||||||||||||
| 3622 | TempDIMacro clone() const { return cloneImpl(); } | ||||||||||||
| 3623 | |||||||||||||
| 3624 | unsigned getLine() const { return Line; } | ||||||||||||
| 3625 | |||||||||||||
| 3626 | StringRef getName() const { return getStringOperand(0); } | ||||||||||||
| 3627 | StringRef getValue() const { return getStringOperand(1); } | ||||||||||||
| 3628 | |||||||||||||
| 3629 | MDString *getRawName() const { return getOperandAs<MDString>(0); } | ||||||||||||
| 3630 | MDString *getRawValue() const { return getOperandAs<MDString>(1); } | ||||||||||||
| 3631 | |||||||||||||
| 3632 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3633 | return MD->getMetadataID() == DIMacroKind; | ||||||||||||
| 3634 | } | ||||||||||||
| 3635 | }; | ||||||||||||
| 3636 | |||||||||||||
| 3637 | class DIMacroFile : public DIMacroNode { | ||||||||||||
| 3638 | friend class LLVMContextImpl; | ||||||||||||
| 3639 | friend class MDNode; | ||||||||||||
| 3640 | |||||||||||||
| 3641 | unsigned Line; | ||||||||||||
| 3642 | |||||||||||||
| 3643 | DIMacroFile(LLVMContext &C, StorageType Storage, unsigned MIType, | ||||||||||||
| 3644 | unsigned Line, ArrayRef<Metadata *> Ops) | ||||||||||||
| 3645 | : DIMacroNode(C, DIMacroFileKind, Storage, MIType, Ops), Line(Line) {} | ||||||||||||
| 3646 | ~DIMacroFile() = default; | ||||||||||||
| 3647 | |||||||||||||
| 3648 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||||||||||
| 3649 | unsigned Line, DIFile *File, | ||||||||||||
| 3650 | DIMacroNodeArray Elements, StorageType Storage, | ||||||||||||
| 3651 | bool ShouldCreate = true) { | ||||||||||||
| 3652 | return getImpl(Context, MIType, Line, static_cast<Metadata *>(File), | ||||||||||||
| 3653 | Elements.get(), Storage, ShouldCreate); | ||||||||||||
| 3654 | } | ||||||||||||
| 3655 | |||||||||||||
| 3656 | static DIMacroFile *getImpl(LLVMContext &Context, unsigned MIType, | ||||||||||||
| 3657 | unsigned Line, Metadata *File, Metadata *Elements, | ||||||||||||
| 3658 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 3659 | |||||||||||||
| 3660 | TempDIMacroFile cloneImpl() const { | ||||||||||||
| 3661 | return getTemporary(getContext(), getMacinfoType(), getLine(), getFile(), | ||||||||||||
| 3662 | getElements()); | ||||||||||||
| 3663 | } | ||||||||||||
| 3664 | |||||||||||||
| 3665 | public: | ||||||||||||
| 3666 | DEFINE_MDNODE_GET(DIMacroFile, | ||||||||||||
| 3667 | (unsigned MIType, unsigned Line, DIFile *File, | ||||||||||||
| 3668 | DIMacroNodeArray Elements), | ||||||||||||
| 3669 | (MIType, Line, File, Elements)) | ||||||||||||
| 3670 | DEFINE_MDNODE_GET(DIMacroFile, | ||||||||||||
| 3671 | (unsigned MIType, unsigned Line, Metadata *File, | ||||||||||||
| 3672 | Metadata *Elements), | ||||||||||||
| 3673 | (MIType, Line, File, Elements)) | ||||||||||||
| 3674 | |||||||||||||
| 3675 | TempDIMacroFile clone() const { return cloneImpl(); } | ||||||||||||
| 3676 | |||||||||||||
| 3677 | void replaceElements(DIMacroNodeArray Elements) { | ||||||||||||
| 3678 | #ifndef NDEBUG | ||||||||||||
| 3679 | for (DIMacroNode *Op : getElements()) | ||||||||||||
| 3680 | assert(is_contained(Elements->operands(), Op) &&(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3681, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
| 3681 | "Lost a macro node during macro node list replacement")(static_cast <bool> (is_contained(Elements->operands (), Op) && "Lost a macro node during macro node list replacement" ) ? void (0) : __assert_fail ("is_contained(Elements->operands(), Op) && \"Lost a macro node during macro node list replacement\"" , "llvm/include/llvm/IR/DebugInfoMetadata.h", 3681, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
| 3682 | #endif | ||||||||||||
| 3683 | replaceOperandWith(1, Elements.get()); | ||||||||||||
| 3684 | } | ||||||||||||
| 3685 | |||||||||||||
| 3686 | unsigned getLine() const { return Line; } | ||||||||||||
| 3687 | DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } | ||||||||||||
| 3688 | |||||||||||||
| 3689 | DIMacroNodeArray getElements() const { | ||||||||||||
| 3690 | return cast_or_null<MDTuple>(getRawElements()); | ||||||||||||
| 3691 | } | ||||||||||||
| 3692 | |||||||||||||
| 3693 | Metadata *getRawFile() const { return getOperand(0); } | ||||||||||||
| 3694 | Metadata *getRawElements() const { return getOperand(1); } | ||||||||||||
| 3695 | |||||||||||||
| 3696 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3697 | return MD->getMetadataID() == DIMacroFileKind; | ||||||||||||
| 3698 | } | ||||||||||||
| 3699 | }; | ||||||||||||
| 3700 | |||||||||||||
| 3701 | /// List of ValueAsMetadata, to be used as an argument to a dbg.value | ||||||||||||
| 3702 | /// intrinsic. | ||||||||||||
| 3703 | class DIArgList : public MDNode { | ||||||||||||
| 3704 | friend class LLVMContextImpl; | ||||||||||||
| 3705 | friend class MDNode; | ||||||||||||
| 3706 | using iterator = SmallVectorImpl<ValueAsMetadata *>::iterator; | ||||||||||||
| 3707 | |||||||||||||
| 3708 | SmallVector<ValueAsMetadata *, 4> Args; | ||||||||||||
| 3709 | |||||||||||||
| 3710 | DIArgList(LLVMContext &C, StorageType Storage, | ||||||||||||
| 3711 | ArrayRef<ValueAsMetadata *> Args) | ||||||||||||
| 3712 | : MDNode(C, DIArgListKind, Storage, std::nullopt), | ||||||||||||
| 3713 | Args(Args.begin(), Args.end()) { | ||||||||||||
| 3714 | track(); | ||||||||||||
| 3715 | } | ||||||||||||
| 3716 | ~DIArgList() { untrack(); } | ||||||||||||
| 3717 | |||||||||||||
| 3718 | static DIArgList *getImpl(LLVMContext &Context, | ||||||||||||
| 3719 | ArrayRef<ValueAsMetadata *> Args, | ||||||||||||
| 3720 | StorageType Storage, bool ShouldCreate = true); | ||||||||||||
| 3721 | |||||||||||||
| 3722 | TempDIArgList cloneImpl() const { | ||||||||||||
| 3723 | return getTemporary(getContext(), getArgs()); | ||||||||||||
| 3724 | } | ||||||||||||
| 3725 | |||||||||||||
| 3726 | void track(); | ||||||||||||
| 3727 | void untrack(); | ||||||||||||
| 3728 | void dropAllReferences(); | ||||||||||||
| 3729 | |||||||||||||
| 3730 | public: | ||||||||||||
| 3731 | DEFINE_MDNODE_GET(DIArgList, (ArrayRef<ValueAsMetadata *> Args), (Args)) | ||||||||||||
| 3732 | |||||||||||||
| 3733 | TempDIArgList clone() const { return cloneImpl(); } | ||||||||||||
| 3734 | |||||||||||||
| 3735 | ArrayRef<ValueAsMetadata *> getArgs() const { return Args; } | ||||||||||||
| 3736 | |||||||||||||
| 3737 | iterator args_begin() { return Args.begin(); } | ||||||||||||
| 3738 | iterator args_end() { return Args.end(); } | ||||||||||||
| 3739 | |||||||||||||
| 3740 | static bool classof(const Metadata *MD) { | ||||||||||||
| 3741 | return MD->getMetadataID() == DIArgListKind; | ||||||||||||
| 3742 | } | ||||||||||||
| 3743 | |||||||||||||
| 3744 | void handleChangedOperand(void *Ref, Metadata *New); | ||||||||||||
| 3745 | }; | ||||||||||||
| 3746 | |||||||||||||
| 3747 | /// Identifies a unique instance of a variable. | ||||||||||||
| 3748 | /// | ||||||||||||
| 3749 | /// Storage for identifying a potentially inlined instance of a variable, | ||||||||||||
| 3750 | /// or a fragment thereof. This guarantees that exactly one variable instance | ||||||||||||
| 3751 | /// may be identified by this class, even when that variable is a fragment of | ||||||||||||
| 3752 | /// an aggregate variable and/or there is another inlined instance of the same | ||||||||||||
| 3753 | /// source code variable nearby. | ||||||||||||
| 3754 | /// This class does not necessarily uniquely identify that variable: it is | ||||||||||||
| 3755 | /// possible that a DebugVariable with different parameters may point to the | ||||||||||||
| 3756 | /// same variable instance, but not that one DebugVariable points to multiple | ||||||||||||
| 3757 | /// variable instances. | ||||||||||||
| 3758 | class DebugVariable { | ||||||||||||
| 3759 | using FragmentInfo = DIExpression::FragmentInfo; | ||||||||||||
| 3760 | |||||||||||||
| 3761 | const DILocalVariable *Variable; | ||||||||||||
| 3762 | std::optional<FragmentInfo> Fragment; | ||||||||||||
| 3763 | const DILocation *InlinedAt; | ||||||||||||
| 3764 | |||||||||||||
| 3765 | /// Fragment that will overlap all other fragments. Used as default when | ||||||||||||
| 3766 | /// caller demands a fragment. | ||||||||||||
| 3767 | static const FragmentInfo DefaultFragment; | ||||||||||||
| 3768 | |||||||||||||
| 3769 | public: | ||||||||||||
| 3770 | DebugVariable(const DbgVariableIntrinsic *DII); | ||||||||||||
| 3771 | |||||||||||||
| 3772 | DebugVariable(const DILocalVariable *Var, | ||||||||||||
| 3773 | std::optional<FragmentInfo> FragmentInfo, | ||||||||||||
| 3774 | const DILocation *InlinedAt) | ||||||||||||
| 3775 | : Variable(Var), Fragment(FragmentInfo), InlinedAt(InlinedAt) {} | ||||||||||||
| 3776 | |||||||||||||
| 3777 | DebugVariable(const DILocalVariable *Var, const DIExpression *DIExpr, | ||||||||||||
| 3778 | const DILocation *InlinedAt) | ||||||||||||
| 3779 | : Variable(Var), | ||||||||||||
| 3780 | Fragment(DIExpr ? DIExpr->getFragmentInfo() : std::nullopt), | ||||||||||||
| 3781 | InlinedAt(InlinedAt) {} | ||||||||||||
| 3782 | |||||||||||||
| 3783 | const DILocalVariable *getVariable() const { return Variable; } | ||||||||||||
| 3784 | std::optional<FragmentInfo> getFragment() const { return Fragment; } | ||||||||||||
| 3785 | const DILocation *getInlinedAt() const { return InlinedAt; } | ||||||||||||
| 3786 | |||||||||||||
| 3787 | FragmentInfo getFragmentOrDefault() const { | ||||||||||||
| 3788 | return Fragment.value_or(DefaultFragment); | ||||||||||||
| 3789 | } | ||||||||||||
| 3790 | |||||||||||||
| 3791 | static bool isDefaultFragment(const FragmentInfo F) { | ||||||||||||
| 3792 | return F == DefaultFragment; | ||||||||||||
| 3793 | } | ||||||||||||
| 3794 | |||||||||||||
| 3795 | bool operator==(const DebugVariable &Other) const { | ||||||||||||
| 3796 | return std::tie(Variable, Fragment, InlinedAt) == | ||||||||||||
| 3797 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||||||||||
| 3798 | } | ||||||||||||
| 3799 | |||||||||||||
| 3800 | bool operator<(const DebugVariable &Other) const { | ||||||||||||
| 3801 | return std::tie(Variable, Fragment, InlinedAt) < | ||||||||||||
| 3802 | std::tie(Other.Variable, Other.Fragment, Other.InlinedAt); | ||||||||||||
| 3803 | } | ||||||||||||
| 3804 | }; | ||||||||||||
| 3805 | |||||||||||||
| 3806 | template <> struct DenseMapInfo<DebugVariable> { | ||||||||||||
| 3807 | using FragmentInfo = DIExpression::FragmentInfo; | ||||||||||||
| 3808 | |||||||||||||
| 3809 | /// Empty key: no key should be generated that has no DILocalVariable. | ||||||||||||
| 3810 | static inline DebugVariable getEmptyKey() { | ||||||||||||
| 3811 | return DebugVariable(nullptr, std::nullopt, nullptr); | ||||||||||||
| 3812 | } | ||||||||||||
| 3813 | |||||||||||||
| 3814 | /// Difference in tombstone is that the Optional is meaningful. | ||||||||||||
| 3815 | static inline DebugVariable getTombstoneKey() { | ||||||||||||
| 3816 | return DebugVariable(nullptr, {{0, 0}}, nullptr); | ||||||||||||
| 3817 | } | ||||||||||||
| 3818 | |||||||||||||
| 3819 | static unsigned getHashValue(const DebugVariable &D) { | ||||||||||||
| 3820 | unsigned HV = 0; | ||||||||||||
| 3821 | const std::optional<FragmentInfo> Fragment = D.getFragment(); | ||||||||||||
| 3822 | if (Fragment) | ||||||||||||
| 3823 | HV = DenseMapInfo<FragmentInfo>::getHashValue(*Fragment); | ||||||||||||
| 3824 | |||||||||||||
| 3825 | return hash_combine(D.getVariable(), HV, D.getInlinedAt()); | ||||||||||||
| 3826 | } | ||||||||||||
| 3827 | |||||||||||||
| 3828 | static bool isEqual(const DebugVariable &A, const DebugVariable &B) { | ||||||||||||
| 3829 | return A == B; | ||||||||||||
| 3830 | } | ||||||||||||
| 3831 | }; | ||||||||||||
| 3832 | |||||||||||||
| 3833 | /// Identifies a unique instance of a whole variable (discards/ignores fragment | ||||||||||||
| 3834 | /// information). | ||||||||||||
| 3835 | class DebugVariableAggregate : public DebugVariable { | ||||||||||||
| 3836 | public: | ||||||||||||
| 3837 | DebugVariableAggregate(const DbgVariableIntrinsic *DVI); | ||||||||||||
| 3838 | DebugVariableAggregate(const DebugVariable &V) | ||||||||||||
| 3839 | : DebugVariable(V.getVariable(), std::nullopt, V.getInlinedAt()) {} | ||||||||||||
| 3840 | }; | ||||||||||||
| 3841 | |||||||||||||
| 3842 | template <> | ||||||||||||
| 3843 | struct DenseMapInfo<DebugVariableAggregate> | ||||||||||||
| 3844 | : public DenseMapInfo<DebugVariable> {}; | ||||||||||||
| 3845 | } // end namespace llvm | ||||||||||||
| 3846 | |||||||||||||
| 3847 | #undef DEFINE_MDNODE_GET_UNPACK_IMPL | ||||||||||||
| 3848 | #undef DEFINE_MDNODE_GET_UNPACK | ||||||||||||
| 3849 | #undef DEFINE_MDNODE_GET | ||||||||||||
| 3850 | |||||||||||||
| 3851 | #endif // LLVM_IR_DEBUGINFOMETADATA_H |