blob: 70d152147519835dd97d76b237fe9cdba8409c2c [file] [edit]
//===-- 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 verifyAMDGPUAlloca(VerifierSupport &VS, const AllocaInst &AI);
void verifyAMDGPUIntrinsicCall(VerifierSupport &VS, Intrinsic::ID ID,
CallBase &Call);
bool isAMDGPUCallBrIntrinsic(Intrinsic::ID ID);
//==============================================================================
} // namespace llvm
#endif // LLVM_LIB_IR_VERIFIERINTERNAL_H