DLA: Add DeduplicateUnionFields Step

Add a step that recognizes if two subtrees of a union node are
topologically equivalent and merges them. This corresponds to removing
duplicate fields in unions.

This deduplication was prevously done while emitting layouts.

A check is inserted into DLAMakeLayouts to assert that, after
constructing unions, no union has only one child, which could be the
case if we didn't deduplicate union fields in the graph.
This commit is contained in:
Alvise de Faveri
2021-09-15 19:15:33 +02:00
committed by Pietro Fezzardi
parent 637bf70ff3
commit 43ae7a91cb
13 changed files with 759 additions and 33 deletions
+24 -4
View File
@@ -8,6 +8,7 @@
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
@@ -24,6 +25,8 @@ using namespace llvm;
using NodeAllocatorT = SpecificBumpPtrAllocator<dla::LayoutTypeSystemNode>;
static Logger<> CollapsedNodePrinter("dla-print-collapsed-in-dot");
void *operator new(size_t, NodeAllocatorT &NodeAllocator) {
return NodeAllocator.Allocate();
}
@@ -93,7 +96,8 @@ static_assert(sizeof(Instance) == (str_len(Instance) + 1));
static_assert(sizeof(Unexpected) == (str_len(Unexpected) + 1));
} // end unnamed namespace
void LayoutTypeSystem::dumpDotOnFile(const char *FName) const {
void debug_function LayoutTypeSystem::dumpDotOnFile(const char *FName,
bool ShowCollapsed) const {
std::error_code EC;
raw_fd_ostream DotFile(FName, EC);
revng_check(not EC, "Could not open file for printing LayoutTypeSystem dot");
@@ -121,7 +125,9 @@ void LayoutTypeSystem::dumpDotOnFile(const char *FName) const {
revng_unreachable();
}
DebugPrinter->printNodeContent(*this, L, DotFile);
if (CollapsedNodePrinter.isEnabled() or ShowCollapsed)
DebugPrinter->printNodeContent(*this, L, DotFile);
DotFile << "\"];\n";
}
@@ -640,6 +646,20 @@ bool LayoutTypeSystem::verifyInheritanceTree() const {
return true;
}
bool LayoutTypeSystem::verifyUnions() const {
using GraphNodeT = const LayoutTypeSystemNode *;
for (GraphNodeT Node : llvm::nodes(this)) {
if (Node->InterferingInfo == AllChildrenAreInterfering
and Node->Successors.size() <= 1) {
if (VerifyDLALog.isEnabled())
revng_check(false);
return false;
}
}
return true;
}
bool LayoutTypeSystem::verifyConflicts() const {
using GraphNodeT = const LayoutTypeSystemNode *;
using LinkT = const LayoutTypeSystemNode::Link;
@@ -647,12 +667,12 @@ bool LayoutTypeSystem::verifyConflicts() const {
for (GraphNodeT Node : llvm::nodes(this)) {
for (auto &Succ : Node->Successors) {
auto HasSameSucc = [&Succ](const LinkT &L2) {
auto HasSameSuccAtOffset0 = [&Succ](const LinkT &L2) {
return isInstanceOff0Edge(L2) and (Succ.first == L2.first);
};
if (isInheritanceEdge(Succ)
and llvm::any_of(Node->Successors, HasSameSucc)) {
and llvm::any_of(Node->Successors, HasSameSuccAtOffset0)) {
if (VerifyDLALog.isEnabled())
revng_check(false);
return false;