mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
Verifier: Move over DISubprogram::Verify()
Move over the remaining (somewhat complicated) check from `DISubprogram::Verify()`. I suspect this check could be optimized -- e.g., it would be nice not to do another full traversal here -- but it's not exactly obvious how. For now, just bring it over as is. Once we have a better model for the "canonical" subprogram of a `Function`, we should enforce that all `!dbg` attachments lead to the canonical one. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@233663 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
81a8d62b94
commit
d3cfcf9614
@ -256,39 +256,7 @@ bool DIType::Verify() const { return isType(); }
|
|||||||
bool DIBasicType::Verify() const { return isBasicType(); }
|
bool DIBasicType::Verify() const { return isBasicType(); }
|
||||||
bool DIDerivedType::Verify() const { return isDerivedType(); }
|
bool DIDerivedType::Verify() const { return isDerivedType(); }
|
||||||
bool DICompositeType::Verify() const { return isCompositeType(); }
|
bool DICompositeType::Verify() const { return isCompositeType(); }
|
||||||
|
bool DISubprogram::Verify() const { return isSubprogram(); }
|
||||||
bool DISubprogram::Verify() const {
|
|
||||||
auto *N = dyn_cast_or_null<MDSubprogram>(DbgNode);
|
|
||||||
if (!N)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If a DISubprogram has an llvm::Function*, then scope chains from all
|
|
||||||
// instructions within the function should lead to this DISubprogram.
|
|
||||||
if (auto *F = getFunction()) {
|
|
||||||
for (auto &BB : *F) {
|
|
||||||
for (auto &I : BB) {
|
|
||||||
MDLocation *DL = I.getDebugLoc();
|
|
||||||
if (!DL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// walk the inlined-at scopes
|
|
||||||
MDScope *Scope = DL->getInlinedAtScope();
|
|
||||||
if (!Scope)
|
|
||||||
return false;
|
|
||||||
while (!isa<MDSubprogram>(Scope)) {
|
|
||||||
Scope = cast<MDLexicalBlockBase>(Scope)->getScope();
|
|
||||||
if (!Scope)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!DISubprogram(Scope).describes(F))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DIGlobalVariable::Verify() const { return isGlobalVariable(); }
|
bool DIGlobalVariable::Verify() const { return isGlobalVariable(); }
|
||||||
bool DIVariable::Verify() const { return isVariable(); }
|
bool DIVariable::Verify() const { return isVariable(); }
|
||||||
|
|
||||||
|
@ -921,6 +921,45 @@ void Verifier::visitMDSubprogram(const MDSubprogram &N) {
|
|||||||
}
|
}
|
||||||
Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags",
|
Assert(!hasConflictingReferenceFlags(N.getFlags()), "invalid reference flags",
|
||||||
&N);
|
&N);
|
||||||
|
|
||||||
|
if (!N.getFunction())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME: Should this be looking through bitcasts?
|
||||||
|
auto *F = dyn_cast<Function>(N.getFunction()->getValue());
|
||||||
|
if (!F)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check that all !dbg attachments lead to back to N (or, at least, another
|
||||||
|
// subprogram that describes the same function).
|
||||||
|
//
|
||||||
|
// FIXME: Check this incrementally while visiting !dbg attachments.
|
||||||
|
// FIXME: Only check when N is the canonical subprogram for F.
|
||||||
|
SmallPtrSet<const MDNode *, 32> Seen;
|
||||||
|
for (auto &BB : *F)
|
||||||
|
for (auto &I : BB) {
|
||||||
|
// Be careful about using MDLocation here since we might be dealing with
|
||||||
|
// broken code (this is the Verifier after all).
|
||||||
|
MDLocation *DL =
|
||||||
|
dyn_cast_or_null<MDLocation>(I.getDebugLoc().getAsMDNode());
|
||||||
|
if (!DL)
|
||||||
|
continue;
|
||||||
|
if (!Seen.insert(DL).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MDLocalScope *Scope = DL->getInlinedAtScope();
|
||||||
|
if (Scope && !Seen.insert(Scope).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
MDSubprogram *SP = Scope ? Scope->getSubprogram() : nullptr;
|
||||||
|
if (SP && !Seen.insert(SP).second)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// FIXME: Once N is canonical, check "SP == &N".
|
||||||
|
Assert(DISubprogram(SP).describes(F),
|
||||||
|
"!dbg attachment points at wrong subprogram for function", &N, F,
|
||||||
|
&I, DL, Scope, SP);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Verifier::visitMDLexicalBlockBase(const MDLexicalBlockBase &N) {
|
void Verifier::visitMDLexicalBlockBase(const MDLexicalBlockBase &N) {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "llvm/IR/MDBuilder.h"
|
#include "llvm/IR/MDBuilder.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/NoFolder.h"
|
#include "llvm/IR/NoFolder.h"
|
||||||
|
#include "llvm/IR/Verifier.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -303,8 +304,8 @@ TEST_F(IRBuilderTest, DIBuilder) {
|
|||||||
0, true, nullptr);
|
0, true, nullptr);
|
||||||
auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0);
|
auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0);
|
||||||
I->setDebugLoc(DebugLoc::get(2, 0, BadScope));
|
I->setDebugLoc(DebugLoc::get(2, 0, BadScope));
|
||||||
EXPECT_FALSE(SP.Verify());
|
|
||||||
DIB.finalize();
|
DIB.finalize();
|
||||||
|
EXPECT_TRUE(verifyModule(*M));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user