Files
revng-revng/lib/DataLayoutAnalysis/Middleend/DLAStep.h
T
Pietro Fezzardi 6f41e625e7 DeduplicateUnionFields is now DeduplicateFields
Before this commit, the dla::Step depended on InterferingInfo, but this
was superfluous.

This commit drops the dependency and enables the Step to run before
ComputeNonInterferingComponents.

This also avoids the need to run ComputeNonInterferingComponents twice
(one before and one after DeduplicateUnionFields), so it can only run
once.
2022-06-08 14:16:51 +02:00

334 lines
8.8 KiB
C++

#pragma once
//
// Copyright (c) rev.ng Labs Srl. See LICENSE.md for details.
//
#include <algorithm>
#include <memory>
#include <type_traits>
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "revng-c/DataLayoutAnalysis/DLATypeSystem.h"
namespace dla {
// Forward declaration for dla::LayoutTypeSystem, that will be defined later.
// For this preliminary implementation, dla::Step does not really need the
// implementation of the dla::LayoutTypeSystem class, because for now we are
// only concerned about the schedule of the Steps, and the Step implementations
// are really just empty.
class LayoutTypeSystem;
class Step {
public:
using IDSet = llvm::SmallPtrSet<const void *, 2>;
using IDSetRef = llvm::SmallPtrSetImpl<const void *> &;
using IDSetConstRef = const llvm::SmallPtrSetImpl<const void *> &;
protected:
const void *StepID;
IDSet Dependencies;
IDSet Invalidated;
Step(const char &C,
std::initializer_list<const void *> D,
std::initializer_list<const void *> I) :
StepID(&C), Dependencies(D), Invalidated(I) {}
Step(const char &C) : Step(C, {}, {}) {}
public:
Step() = delete;
virtual ~Step() = default;
/// Runs the Step on TS, returns true if it has applied changes to TS.
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) = 0;
IDSetConstRef getDependencies() const { return Dependencies; }
IDSetConstRef getInvalidated() const { return Invalidated; }
const void *getStepID() const { return StepID; };
};
/// Collapses strongly connected components made of equality edges
//
// After the execution of this step, the LayoutTypeSystem graph should not
// contain equality edges anymore
class CollapseEqualitySCC : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
CollapseEqualitySCC() : Step(ID){};
virtual ~CollapseEqualitySCC() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// Collapses strongly connected components in the type system made of
/// instance-at-offset-0 edges
class CollapseInstanceAtOffset0SCC : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
CollapseInstanceAtOffset0SCC() : Step(ID){};
virtual ~CollapseInstanceAtOffset0SCC() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that simplifies instance-at-offset-0 edges, to reduce the
/// unnecessary layers of nested types
class SimplifyInstanceAtOffset0 : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
SimplifyInstanceAtOffset0() :
Step(ID,
// Dependencies
{ CollapseInstanceAtOffset0SCC::getID() },
// Invalidated
{}) {}
virtual ~SimplifyInstanceAtOffset0() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that removes leaf nodes without valid layout information
//
// Initially valid layout information is simply represented by accesses, but we
// expect this to be possibly user provded for leafs that otherwise had no valid
// layout information, such as calls to external library functions.
class PruneLayoutNodesWithoutLayout : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
PruneLayoutNodesWithoutLayout() : Step(ID) {}
virtual ~PruneLayoutNodesWithoutLayout() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that merge pointer nodes pointing to the same layout
class MergePointerNodes : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
MergePointerNodes() : Step(ID) {}
virtual ~MergePointerNodes() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that computes and propagates informations on accesses and type
/// sizes.
class ComputeUpperMemberAccesses : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
ComputeUpperMemberAccesses() :
Step(ID,
// Dependencies
{
CollapseInstanceAtOffset0SCC::getID(),
CollapseEqualitySCC::getID(),
PruneLayoutNodesWithoutLayout::getID(),
},
// Invalidated
{}) {}
virtual ~ComputeUpperMemberAccesses() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that collapses nodes that have a single child at offset 0
class CollapseSingleChild : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
static bool collapseSingle(LayoutTypeSystem &TS, LayoutTypeSystemNode *Node);
CollapseSingleChild() :
Step(ID,
// Dependencies
{ ComputeUpperMemberAccesses::getID() },
// Invalidated
{}) {}
virtual ~CollapseSingleChild() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that decompose the LayoutTypeSystem into components, each of which
/// cannot overlap with others
class ComputeNonInterferingComponents : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
ComputeNonInterferingComponents() :
Step(ID,
// Dependencies
{ ComputeUpperMemberAccesses::getID() },
// Invalidated
{}) {}
virtual ~ComputeNonInterferingComponents() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that removes invalide stride edges
class RemoveInvalidStrideEdges : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
RemoveInvalidStrideEdges() :
Step(ID,
// Dependencies
{ ComputeUpperMemberAccesses::getID() },
// Invalidated
{ ComputeUpperMemberAccesses::getID(),
PruneLayoutNodesWithoutLayout::getID() }) {}
virtual ~RemoveInvalidStrideEdges() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that removes invalide pointer edges
class RemoveInvalidPointers : public Step {
static const char ID;
size_t PointerSize;
public:
static const constexpr void *getID() { return &ID; }
RemoveInvalidPointers(size_t PtrSize) : Step(ID), PointerSize(PtrSize) {}
virtual ~RemoveInvalidPointers() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
/// dla::Step that merges structurally identical subtrees of an interfering
/// node.
class DeduplicateFields : public Step {
static const char ID;
public:
static const constexpr void *getID() { return &ID; }
DeduplicateFields() :
Step(ID,
// Dependencies
{},
// Invalidated
{}) {}
virtual ~DeduplicateFields() override = default;
virtual bool runOnTypeSystem(LayoutTypeSystem &TS) override;
};
template<typename IterT>
bool intersect(IterT I1, IterT E1, IterT I2, IterT E2) {
while ((I1 != E1) and (I2 != E2)) {
if (*I1 < *I2)
++I1;
else if (*I2 < *I1)
++I2;
else
return true;
}
return false;
}
template<typename RangeT>
bool intersect(const RangeT &R1, const RangeT &R2) {
return intersect(R1.begin(), R1.end(), R2.begin(), R2.end());
}
class StepManager {
public:
enum StepState {
NewlyAdded,
Invalidated,
Done,
};
public:
llvm::SmallVector<std::unique_ptr<Step>, 16> Schedule;
llvm::SmallPtrSet<const void *, 16> InsertedSteps;
llvm::SmallPtrSet<const void *, 16> InvalidatedSteps;
using sched_const_iterator = decltype(Schedule)::const_iterator;
using sched_const_range = llvm::iterator_range<sched_const_iterator>;
public:
StepManager() : Schedule(), InsertedSteps(), InvalidatedSteps() {}
/// Adds a Step to the StepManager, moving ownership into it.
[[nodiscard]] bool addStep(std::unique_ptr<Step> S);
template<typename StepT, typename... ArgsT>
[[nodiscard]] bool addStep(ArgsT &&...Args) {
return addStep(std::make_unique<StepT>(std::forward<ArgsT &&>(Args)...));
}
/// Runs the added steps
void run(LayoutTypeSystem &TS);
/// Drops all the scheduled steps
void reset() {
Schedule.clear();
InsertedSteps.clear();
InvalidatedSteps.clear();
}
bool hasValidSchedule() const {
return not intersect(InsertedSteps, InvalidatedSteps);
}
/// Get the number of scheduled steps
auto getNumSteps() const { return Schedule.size(); }
// Methods for const iteration on Schedule
sched_const_iterator sched_begin() const { return Schedule.begin(); }
sched_const_iterator sched_end() const { return Schedule.end(); }
sched_const_range sched() const {
return llvm::make_range(sched_begin(), sched_end());
}
};
} // end namespace dla