mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
ab125b35b0
Change company name to "rev.ng Labs Srl" in all license headers to reflect changed company name and legal status Add missing license headers to files that didn't have one
159 lines
4.1 KiB
C++
159 lines
4.1 KiB
C++
/// \file ReachabilityPass.cpp
|
|
/// FunctionPass that computes the reachability for the nodes of a given
|
|
/// Function
|
|
|
|
//
|
|
// Copyright rev.ng Labs Srl. See LICENSE.md for details.
|
|
//
|
|
|
|
#include <sstream>
|
|
|
|
#include "llvm/ADT/PostOrderIterator.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
#include "revng/Support/Debug.h"
|
|
#include "revng/Support/IRHelpers.h"
|
|
|
|
#include "ReachabilityPass.h"
|
|
|
|
using namespace llvm;
|
|
|
|
char ReachabilityPass::ID = 0;
|
|
using Reg = RegisterPass<ReachabilityPass>;
|
|
static Reg X("reachability", "Compute reachability information", true, true);
|
|
|
|
bool ReachabilityPass::runOnFunction(Function &F) {
|
|
|
|
// Clean class members.
|
|
ReachableBlocks.clear();
|
|
|
|
std::map<BasicBlock *, unsigned> BBToIndex;
|
|
std::map<unsigned, BasicBlock *> IndexToBB;
|
|
unsigned Index = 0;
|
|
|
|
// Initialize a mapping between basic blocks and their index.
|
|
for (BasicBlock &BB : F) {
|
|
BBToIndex[&BB] = Index;
|
|
IndexToBB[Index] = &BB;
|
|
Index++;
|
|
}
|
|
|
|
// Maximum index of the basic blocks.
|
|
unsigned Dimension = Index;
|
|
unsigned MaxIndex = Index - 1;
|
|
|
|
// Create and initialize the incidence matrix.
|
|
using Bool2DMatrix = std::vector<std::vector<bool>>;
|
|
Bool2DMatrix Matrix(Dimension, std::vector<bool>(Dimension, false));
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
if (i == j) {
|
|
Matrix[i][j] = 1;
|
|
} else {
|
|
Matrix[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill the incidence matrix with the connections at single step.
|
|
for (BasicBlock &BB : F) {
|
|
unsigned BBIndex = BBToIndex[&BB];
|
|
for (BasicBlock *Successor : make_range(succ_begin(&BB), succ_end(&BB))) {
|
|
unsigned SuccessorIndex = BBToIndex[Successor];
|
|
Matrix[BBIndex][SuccessorIndex] = 1;
|
|
}
|
|
}
|
|
|
|
dbg << "Mapping:\n";
|
|
for (auto &Elem : BBToIndex) {
|
|
dbg << getName(Elem.first) << " " << Elem.second << "\n";
|
|
}
|
|
|
|
dbg << "Matrix is:\n";
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
dbg << Matrix[i][j] << " ";
|
|
}
|
|
dbg << "\n";
|
|
}
|
|
|
|
bool Change = true;
|
|
while (Change) {
|
|
Change = false;
|
|
|
|
Bool2DMatrix MatrixClosure(Dimension, std::vector<bool>(Dimension, false));
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
bool Value = 0;
|
|
for (unsigned k = 0; k <= MaxIndex; k++) {
|
|
Value = Value or (Matrix[i][k] and Matrix[k][j]);
|
|
}
|
|
MatrixClosure[i][j] = Value;
|
|
}
|
|
}
|
|
|
|
dbg << "Matrix closure is:\n";
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
dbg << MatrixClosure[i][j] << " ";
|
|
}
|
|
dbg << "\n";
|
|
}
|
|
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
bool OldValue = Matrix[i][j];
|
|
Matrix[i][j] = Matrix[i][j] or MatrixClosure[i][j];
|
|
bool NewValue = Matrix[i][j];
|
|
if (OldValue != NewValue) {
|
|
Change = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
dbg << "Matrix sum is:\n";
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
dbg << Matrix[i][j] << " ";
|
|
}
|
|
dbg << "\n";
|
|
}
|
|
}
|
|
|
|
// Fill the final data structure.
|
|
for (unsigned i = 0; i <= MaxIndex; i++) {
|
|
for (unsigned j = 0; j <= MaxIndex; j++) {
|
|
BasicBlock *SourceBB = IndexToBB[i];
|
|
BasicBlock *TargetBB = IndexToBB[j];
|
|
if (Matrix[i][j]) {
|
|
ReachableBlocks[SourceBB].insert(TargetBB);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print the final data structure.
|
|
for (auto &It : ReachableBlocks) {
|
|
dbg << "From " << getName(It.first) << " I can reach:\n";
|
|
for (auto Elem : It.second) {
|
|
dbg << getName(Elem) << "\n";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ReachabilityPass::existsPath(BasicBlock *Source, BasicBlock *Target) {
|
|
if (ReachableBlocks[Source].count(Target) != 0) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
std::set<BasicBlock *> &ReachabilityPass::reachableFrom(BasicBlock *Source) {
|
|
return ReachableBlocks[Source];
|
|
}
|