| //===-- VerifierInternal.h - Internal verifier infrastructure --------------==// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Shared definitions used by the verifier implementation files. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_LIB_IR_VERIFIERINTERNAL_H | |
| #define LLVM_LIB_IR_VERIFIERINTERNAL_H | |
| #include "llvm/ADT/Twine.h" | |
| #include "llvm/IR/Attributes.h" | |
| #include "llvm/IR/DebugInfoMetadata.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/IR/Metadata.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/ModuleSlotTracker.h" | |
| #include "llvm/IR/Value.h" | |
| #include "llvm/Support/Casting.h" | |
| #include "llvm/Support/Printable.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include "llvm/TargetParser/Triple.h" | |
| namespace llvm { | |
| struct VerifierSupport { | |
| raw_ostream *OS; | |
| const Module &M; | |
| ModuleSlotTracker MST; | |
| const Triple &TT; | |
| const DataLayout &DL; | |
| LLVMContext &Context; | |
| /// Track the brokenness of the module while recursively visiting. | |
| bool Broken = false; | |
| /// Broken debug info can be "recovered" from by stripping the debug info. | |
| bool BrokenDebugInfo = false; | |
| /// Whether to treat broken debug info as an error. | |
| bool TreatBrokenDebugInfoAsError = true; | |
| explicit VerifierSupport(raw_ostream *OS, const Module &M) | |
| : OS(OS), M(M), MST(&M), TT(M.getTargetTriple()), DL(M.getDataLayout()), | |
| Context(M.getContext()) {} | |
| private: | |
| void Write(const Module *M) { | |
| *OS << "; ModuleID = '" << M->getModuleIdentifier() << "'\n"; | |
| } | |
| void Write(const Value *V) { | |
| if (V) | |
| Write(*V); | |
| } | |
| void Write(const Value &V) { | |
| if (isa<Instruction>(V)) { | |
| V.print(*OS, MST); | |
| *OS << '\n'; | |
| } else { | |
| V.printAsOperand(*OS, true, MST); | |
| *OS << '\n'; | |
| } | |
| } | |
| void Write(const DbgRecord *DR) { | |
| if (DR) { | |
| DR->print(*OS, MST, false); | |
| *OS << '\n'; | |
| } | |
| } | |
| void Write(DbgVariableRecord::LocationType Type) { | |
| switch (Type) { | |
| case DbgVariableRecord::LocationType::Value: | |
| *OS << "value"; | |
| break; | |
| case DbgVariableRecord::LocationType::Declare: | |
| *OS << "declare"; | |
| break; | |
| case DbgVariableRecord::LocationType::DeclareValue: | |
| *OS << "declare_value"; | |
| break; | |
| case DbgVariableRecord::LocationType::Assign: | |
| *OS << "assign"; | |
| break; | |
| case DbgVariableRecord::LocationType::End: | |
| *OS << "end"; | |
| break; | |
| case DbgVariableRecord::LocationType::Any: | |
| *OS << "any"; | |
| break; | |
| }; | |
| } | |
| void Write(const Metadata *MD) { | |
| if (!MD) | |
| return; | |
| MD->print(*OS, MST, &M); | |
| *OS << '\n'; | |
| } | |
| template <class T> void Write(const MDTupleTypedArrayWrapper<T> &MD) { | |
| Write(MD.get()); | |
| } | |
| void Write(const NamedMDNode *NMD) { | |
| if (!NMD) | |
| return; | |
| NMD->print(*OS, MST); | |
| *OS << '\n'; | |
| } | |
| void Write(Type *T) { | |
| if (!T) | |
| return; | |
| *OS << ' ' << *T; | |
| } | |
| void Write(const Comdat *C) { | |
| if (!C) | |
| return; | |
| *OS << *C; | |
| } | |
| void Write(const APInt *AI) { | |
| if (!AI) | |
| return; | |
| *OS << *AI << '\n'; | |
| } | |
| void Write(const unsigned i) { *OS << i << '\n'; } | |
| // NOLINTNEXTLINE(readability-identifier-naming) | |
| void Write(const Attribute *A) { | |
| if (!A) | |
| return; | |
| *OS << A->getAsString() << '\n'; | |
| } | |
| // NOLINTNEXTLINE(readability-identifier-naming) | |
| void Write(const AttributeSet *AS) { | |
| if (!AS) | |
| return; | |
| *OS << AS->getAsString() << '\n'; | |
| } | |
| // NOLINTNEXTLINE(readability-identifier-naming) | |
| void Write(const AttributeList *AL) { | |
| if (!AL) | |
| return; | |
| AL->print(*OS); | |
| } | |
| void Write(Printable P) { *OS << P; } | |
| template <typename T> void Write(ArrayRef<T> Vs) { | |
| for (const T &V : Vs) | |
| Write(V); | |
| } | |
| template <typename T1, typename... Ts> | |
| void WriteTs(const T1 &V1, const Ts &...Vs) { | |
| Write(V1); | |
| WriteTs(Vs...); | |
| } | |
| template <typename... Ts> void WriteTs() {} | |
| public: | |
| /// A check failed, so printout out the condition and the message. | |
| /// | |
| /// This provides a nice place to put a breakpoint if you want to see why | |
| /// something is not correct. | |
| void CheckFailed(const Twine &Message) { | |
| if (OS) | |
| *OS << Message << '\n'; | |
| Broken = true; | |
| } | |
| /// A check failed (with values to print). | |
| /// | |
| /// This calls the Message-only version so that the above is easier to set a | |
| /// breakpoint on. | |
| template <typename T1, typename... Ts> | |
| void CheckFailed(const Twine &Message, const T1 &V1, const Ts &...Vs) { | |
| CheckFailed(Message); | |
| if (OS) | |
| WriteTs(V1, Vs...); | |
| } | |
| /// A debug info check failed. | |
| void DebugInfoCheckFailed(const Twine &Message) { | |
| if (OS) | |
| *OS << Message << '\n'; | |
| Broken |= TreatBrokenDebugInfoAsError; | |
| BrokenDebugInfo = true; | |
| } | |
| /// A debug info check failed (with values to print). | |
| template <typename T1, typename... Ts> | |
| void DebugInfoCheckFailed(const Twine &Message, const T1 &V1, | |
| const Ts &...Vs) { | |
| DebugInfoCheckFailed(Message); | |
| if (OS) | |
| WriteTs(V1, Vs...); | |
| } | |
| }; | |
| //============================================================================== | |
| // AMDGPU-specific verification functions | |
| void verifyAMDGPUModuleFlag(VerifierSupport &VS, const MDString *ID, | |
| Module::ModFlagBehavior MFB, const MDNode *Op); | |
| void verifyAMDGPUFunctionMetadata(VerifierSupport &VS, const Function &F); | |
| void verifyAMDGPUGlobalVariable(VerifierSupport &VS, const GlobalVariable &GV); | |
| void verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI); | |
| void verifyAMDGPUIntrinsicCall(VerifierSupport &VS, Intrinsic::ID ID, | |
| CallBase &Call); | |
| bool isAMDGPUCallBrIntrinsic(Intrinsic::ID ID); | |
| //============================================================================== | |
| // NVVM-specific verification functions | |
| void verifyNVVMIntrinsicCall(VerifierSupport &VS, Intrinsic::ID ID, | |
| CallBase &Call); | |
| //============================================================================== | |
| } // namespace llvm | |
| #endif // LLVM_LIB_IR_VERIFIERINTERNAL_H |