mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
79460c6933
A class or a struct type A can be a forward declaration and refer to another type B in PDB, so we need to follow the references. We pre-create type for B, when we face type A, and then, when we visit type B, we populate the fields for the model::type we pre-created. In addition, this patch fixes some minor/side bugs: - Handle SHORT/Int16Short simple type - Do not delete model::Function if Prototype is invalid.
84 lines
2.5 KiB
C++
84 lines
2.5 KiB
C++
/// \file Processing.cpp
|
|
/// A collection of helper functions to improve the quality of the model/make it
|
|
/// valid.
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/ADT/DepthFirstIterator.h"
|
|
|
|
#include "revng/ADT/GenericGraph.h"
|
|
#include "revng/Model/Processing.h"
|
|
#include "revng/Support/Debug.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace model {
|
|
|
|
template<typename T>
|
|
void purgeFunctions(T &Functions,
|
|
const std::set<const model::Type *> &ToDelete) {
|
|
auto Begin = Functions.begin();
|
|
for (auto It = Begin; It != Functions.end(); ++It) {
|
|
if (not It->Prototype().isValid()
|
|
or ToDelete.contains(It->Prototype().get())) {
|
|
It->Prototype() = TupleTreeReference<model::Type, model::Binary>();
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned dropTypesDependingOnTypes(TupleTree<model::Binary> &Model,
|
|
const std::set<const model::Type *> &Types) {
|
|
// TODO: in case we reach a StructField or UnionField, we should drop the
|
|
// field and not proceed any further
|
|
struct TypeNode {
|
|
const model::Type *T;
|
|
};
|
|
|
|
using Graph = GenericGraph<ForwardNode<TypeNode>>;
|
|
|
|
Graph ReverseDependencyGraph;
|
|
|
|
// Create nodes in reverse dependency graph
|
|
std::map<const model::Type *, ForwardNode<TypeNode> *> TypeToNode;
|
|
for (UpcastablePointer<model::Type> &T : Model->Types())
|
|
TypeToNode[T.get()] = ReverseDependencyGraph.addNode(TypeNode{ T.get() });
|
|
|
|
// Register edges
|
|
for (UpcastablePointer<model::Type> &T : Model->Types()) {
|
|
// Ignore dependencies of types we need to drop
|
|
if (Types.contains(T.get()))
|
|
continue;
|
|
|
|
for (const model::QualifiedType &QT : T->edges()) {
|
|
auto *DependantType = QT.UnqualifiedType().get();
|
|
TypeToNode.at(DependantType)->addSuccessor(TypeToNode.at(T.get()));
|
|
}
|
|
}
|
|
|
|
// Prepare for deletion all the nodes reachable from Types
|
|
std::set<const model::Type *> ToDelete;
|
|
for (const model::Type *Type : Types) {
|
|
for (const auto *Node : depth_first(TypeToNode.at(Type))) {
|
|
ToDelete.insert(Node->T);
|
|
}
|
|
}
|
|
|
|
// Purge both dynamic and local functions depending on Types
|
|
purgeFunctions(Model->ImportedDynamicFunctions(), ToDelete);
|
|
purgeFunctions(Model->Functions(), ToDelete);
|
|
|
|
// Purge types depending on unresolved Types
|
|
for (auto It = Model->Types().begin(); It != Model->Types().end();) {
|
|
if (ToDelete.contains(It->get()))
|
|
It = Model->Types().erase(It);
|
|
else
|
|
++It;
|
|
}
|
|
|
|
return ToDelete.size();
|
|
}
|
|
|
|
} // namespace model
|