[Verifier] Iteratively traverse all indirect users.

The recursive implementation can run into stack overflows, e.g. like in PR52844.

The order the users are visited changes, but for the current use case
this only impacts the order error messages are emitted.
This commit is contained in:
Florian Hahn 2021-12-23 23:20:11 +01:00
parent 5fd328c45f
commit 5d68dc184e
No known key found for this signature in database
GPG Key ID: 60242B98015C34AE
2 changed files with 18 additions and 13 deletions

View File

@ -602,17 +602,22 @@ void Verifier::visit(Instruction &I) {
InstVisitor<Verifier>::visit(I);
}
// Helper to recursively iterate over indirect users. By
// returning false, the callback can ask to stop recursing
// further.
// Helper to iterate over indirect users. By returning false, the callback can ask to stop traversing further.
static void forEachUser(const Value *User,
SmallPtrSet<const Value *, 32> &Visited,
llvm::function_ref<bool(const Value *)> Callback) {
if (!Visited.insert(User).second)
return;
for (const Value *TheNextUser : User->materialized_users())
if (Callback(TheNextUser))
forEachUser(TheNextUser, Visited, Callback);
SmallVector<const Value *> WorkList;
append_range(WorkList, User->materialized_users());
while (!WorkList.empty()) {
const Value *Cur = WorkList.pop_back_val();
if (!Visited.insert(Cur).second)
continue;
if (Callback(Cur))
append_range(WorkList, Cur->materialized_users());
}
}
void Verifier::visitGlobalValue(const GlobalValue &GV) {

View File

@ -136,17 +136,17 @@ TEST(VerifierTest, CrossModuleRef) {
raw_string_ostream ErrorOS(Error);
EXPECT_TRUE(verifyModule(M2, &ErrorOS));
EXPECT_TRUE(StringRef(ErrorOS.str())
.equals("Global is used by function in a different module\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"
"i32 ()* @foo3\n"
"; ModuleID = 'M3'\n"
"Global is referenced in a different module!\n"
.equals("Global is referenced in a different module!\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"
" %call = call i32 @foo2()\n"
"i32 ()* @foo1\n"
"; ModuleID = 'M1'\n"));
"; ModuleID = 'M1'\n"
"Global is used by function in a different module\n"
"i32 ()* @foo2\n"
"; ModuleID = 'M2'\n"
"i32 ()* @foo3\n"
"; ModuleID = 'M3'\n"));
Error.clear();
EXPECT_TRUE(verifyModule(M1, &ErrorOS));