Files
revng-revng/lib/DataLayoutAnalysis/Middleend/DLAPruneLayoutNodesWithoutLayout.cpp
T
Alvise de Faveri 4c8215fc47 DLA: Add pointers
* Changes to the `LayoutTypeSystem` graph

Pointers are identified in the TypeSystem graph as leaf nodes which
have a new type of edge (PointerEdge) that connects them to another
node of the graph. The destination of the edge represents the layout of
the pointed type.

* Changes to the Front-end

Pointer edges, and their destination nodes, are created by the DLA
front-end (`DLACreateIntraProceduralTypes`) whenever an access node has
a size that is compatible with the size of a pointer in the current
Architecture.
Successors might then be added to the newly generated node, if any,
by looking up the llvm::Value it is attached to.

* Changes to the Middle-end

Most of the DLA passes should ignore Pointer Edges, so they are modified
accordingly. Most notably, nodes that represent pointed layouts should
never be merged/pruned-off.

* Changes to the Back-end

The `TypeDeclCreationAction` of the decompiler and the `DLAMakeLayouts`
step of the DLA back-end are modified to take into account the new
information about pointers.

⚠️ There is a known issue with this version of the decompiler,
namely the fact that type loops are not detected and can cause the
emitter to enter an infinite loop.
2021-11-16 17:00:34 +01:00

85 lines
2.2 KiB
C++

//
// Copyright (c) rev.ng Srls. See LICENSE.md for details.
//
#include <algorithm>
#include <set>
#include "llvm/ADT/PostOrderIterator.h"
#include "revng/ADT/FilteredGraphTraits.h"
#include "revng/Support/Debug.h"
#include "revng-c/DataLayoutAnalysis/DLATypeSystem.h"
#include "DLAStep.h"
using namespace llvm;
static Logger<> Log("dla-prune");
namespace dla {
using LTSN = LayoutTypeSystemNode;
using GraphNodeT = LTSN *;
using NonPointerFilterT = EdgeFilteredGraph<GraphNodeT, isNotPointerEdge>;
bool PruneLayoutNodesWithoutLayout::runOnTypeSystem(LayoutTypeSystem &TS) {
bool Changed = false;
using LTSN = LayoutTypeSystemNode;
if (Log.isEnabled())
TS.dumpDotOnFile("before-prune.dot");
if (VerifyLog.isEnabled())
revng_assert(TS.verifyDAG() and TS.verifyInheritanceTree());
std::set<const LTSN *> Visited;
std::set<LTSN *> ToRemove;
for (LTSN *Root : llvm::nodes(&TS)) {
revng_assert(Root != nullptr);
if (not isRoot(Root))
continue;
revng_log(Log, "# Starting from Root: " << Root->ID);
for (LTSN *N : post_order_ext(NonPointerFilterT(Root), Visited)) {
revng_log(Log, "## Visiting N: " << N->ID);
revng_log(Log, "## Is Leaf: " << isLeaf(N));
if (N->Size > 0) {
revng_log(Log, "### has size " << N->Size << " !");
continue;
}
using GT = GraphTraits<NonPointerFilterT>;
if (std::any_of(GT::child_begin(N),
GT::child_end(N),
[&ToRemove](LTSN *Chld) {
return ToRemove.count(Chld) == 0;
})) {
revng_log(Log, "### ChildHasLayout(N)!");
continue;
}
// Here N does not have valid layout, nor any of its child has.
revng_log(Log, "#### Queuing for removal: " << N->ID);
ToRemove.insert(N);
}
}
Changed = not ToRemove.empty();
for (LTSN *N : ToRemove) {
revng_log(Log, "# Removing: " << N->ID);
TS.removeNode(N);
}
if (VerifyLog.isEnabled())
revng_assert(TS.verifyDAG() and TS.verifyInheritanceTree()
and TS.verifyLeafs());
if (Log.isEnabled())
TS.dumpDotOnFile("after-prune.dot");
return Changed;
}
} // end namespace dla