Files
revng-revng/lib/Yield/ControlFlow/FallthroughDetection.cpp
T
Alessandro Di Federico 5820908675 Remove and ban \file
2025-12-16 17:41:55 +01:00

51 lines
1.7 KiB
C++

//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/EarlyFunctionAnalysis/CFGHelpers.h"
#include "revng/Model/Binary.h"
#include "revng/Support/MetaAddress.h"
#include "revng/Yield/ControlFlow/FallthroughDetection.h"
#include "revng/Yield/Function.h"
const yield::BasicBlock *
yield::cfg::detectFallthrough(const yield::BasicBlock &BasicBlock,
const yield::Function &Function,
const model::Binary &Binary) {
const yield::BasicBlock *Result = nullptr;
for (const auto &Edge : BasicBlock.Successors()) {
auto &&[NextAddress,
_] = efa::parseSuccessor(*Edge, BasicBlock.nextBlock(), Binary);
if (NextAddress.isValid() && NextAddress == BasicBlock.nextBlock()) {
if (auto Iterator = Function.Blocks().find(NextAddress);
Iterator != Function.Blocks().end()) {
if (Iterator->IsLabelAlwaysRequired() == false) {
revng_assert(Result == nullptr,
"Multiple targets with the same address");
Result = &*Iterator;
}
}
}
}
return Result;
}
llvm::SmallVector<const yield::BasicBlock *, 8>
yield::cfg::labeledBlock(const yield::BasicBlock &BasicBlock,
const yield::Function &Function,
const model::Binary &Binary) {
// Blocks that are a part of another labeled block cannot start a new one.
if (BasicBlock.IsLabelAlwaysRequired() == false)
return {};
llvm::SmallVector<const yield::BasicBlock *, 8> Result = { &BasicBlock };
auto Next = detectFallthrough(BasicBlock, Function, Binary);
while (Next != nullptr)
Next = detectFallthrough(*Result.emplace_back(Next), Function, Binary);
return Result;
}