clang 20.0.0 (based on r547379) from build 12806354. Bug: http://b/379133546 Test: N/A Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
90 lines
2.4 KiB
C++
90 lines
2.4 KiB
C++
//===-- Analysis/EHUtils.h - Exception handling related utils --*-//C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
|
|
#ifndef LLVM_ANALYSIS_EHUTILS_H
|
|
#define LLVM_ANALYSIS_EHUTILS_H
|
|
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
|
namespace llvm {
|
|
|
|
/// Compute a list of blocks that are only reachable via EH paths.
|
|
template <typename FunctionT, typename BlockT>
|
|
static void computeEHOnlyBlocks(FunctionT &F, DenseSet<BlockT *> &EHBlocks) {
|
|
// A block can be unknown if its not reachable from anywhere
|
|
// EH if its only reachable from start blocks via some path through EH pads
|
|
// NonEH if it's reachable from Non EH blocks as well.
|
|
enum Status { Unknown = 0, EH = 1, NonEH = 2 };
|
|
DenseSet<BlockT *> WorkList;
|
|
DenseMap<BlockT *, Status> Statuses;
|
|
|
|
auto GetStatus = [&](BlockT *BB) {
|
|
if (Statuses.contains(BB))
|
|
return Statuses[BB];
|
|
else
|
|
return Unknown;
|
|
};
|
|
|
|
auto CheckPredecessors = [&](BlockT *BB, Status Stat) {
|
|
for (auto *PredBB : predecessors(BB)) {
|
|
Status PredStatus = GetStatus(PredBB);
|
|
// If status of predecessor block has gone above current block
|
|
// we update current blocks status.
|
|
if (PredStatus > Stat)
|
|
Stat = PredStatus;
|
|
}
|
|
return Stat;
|
|
};
|
|
|
|
auto AddSuccesors = [&](BlockT *BB) {
|
|
for (auto *SuccBB : successors(BB)) {
|
|
if (!SuccBB->isEHPad())
|
|
WorkList.insert(SuccBB);
|
|
}
|
|
};
|
|
|
|
// Insert the successors of start block and landing pads successor.
|
|
BlockT *StartBlock = &F.front();
|
|
Statuses[StartBlock] = NonEH;
|
|
AddSuccesors(StartBlock);
|
|
|
|
for (auto &BB : F) {
|
|
if (BB.isEHPad()) {
|
|
AddSuccesors(&BB);
|
|
Statuses[&BB] = EH;
|
|
}
|
|
}
|
|
|
|
// Worklist iterative algorithm.
|
|
while (!WorkList.empty()) {
|
|
auto *BB = *WorkList.begin();
|
|
WorkList.erase(BB);
|
|
|
|
Status OldStatus = GetStatus(BB);
|
|
|
|
// Check on predecessors and check for
|
|
// Status update.
|
|
Status NewStatus = CheckPredecessors(BB, OldStatus);
|
|
|
|
// Did the block status change?
|
|
bool Changed = OldStatus != NewStatus;
|
|
if (Changed) {
|
|
AddSuccesors(BB);
|
|
Statuses[BB] = NewStatus;
|
|
}
|
|
}
|
|
|
|
for (auto Entry : Statuses) {
|
|
if (Entry.second == EH)
|
|
EHBlocks.insert(Entry.first);
|
|
}
|
|
}
|
|
} // namespace llvm
|
|
|
|
#endif
|