mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This is apart of the work to change ARC so that all of the dataflow operations are delegated to visitors which allow for behavior to be specialized depending on the transformation kind. This will allow for users to add new behavior to the ARC optimizer will minimally touching the actual dataflow. Swift SVN r26777
145 lines
4.7 KiB
C++
145 lines
4.7 KiB
C++
//===--- RCStateTransition.h -------------------------------*- C++ -*------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SILANALYSIS_RCSTATETRANSITION_H
|
|
#define SWIFT_SILANALYSIS_RCSTATETRANSITION_H
|
|
|
|
#include "swift/SIL/SILArgument.h"
|
|
#include "swift/SIL/SILInstruction.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include <cstdint>
|
|
|
|
namespace swift {
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RCStateTransitionKind
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// The kind of a RCStateTransition.
|
|
enum class RCStateTransitionKind : uint8_t {
|
|
#define KIND(K) K,
|
|
#define ABSTRACT_VALUE(Name, StartKind, EndKind) \
|
|
Name ## _Start = StartKind, Name ## _End = EndKind,
|
|
#include "RCStateTransition.def"
|
|
};
|
|
|
|
RCStateTransitionKind getRCStateTransitionKind(ValueBase *V);
|
|
|
|
/// Define predicates to test for RCStateTransition abstract value kinds.
|
|
#define ABSTRACT_VALUE(Name, Start, End) \
|
|
bool isRCStateTransition ## Name(RCStateTransitionKind Kind);
|
|
#include "RCStateTransition.def"
|
|
|
|
|
|
template <typename ImplTy, typename ResultTy>
|
|
class RCStateTransitionKindVisitor {
|
|
ImplTy &asImpl() { return *reinterpret_cast<ImplTy *>(this); }
|
|
public:
|
|
#define KIND(K) ResultTy visit ## K(SILInstruction *) { return ResultTy(); }
|
|
#include "RCStateTransition.def"
|
|
|
|
ResultTy visit(SILInstruction *I) {
|
|
switch (getRCStateTransitionKind(I)) {
|
|
#define KIND(K) \
|
|
case RCStateTransitionKind::K: \
|
|
return asImpl().visit ## K(I);
|
|
#include "RCStateTransition.def"
|
|
}
|
|
llvm_unreachable("Covered switch isn't covered?!");
|
|
}
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RCStateTransition
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
template <typename T> struct RefCountState;
|
|
|
|
/// Represents a transition in the RC history of a ref count.
|
|
class RCStateTransition {
|
|
template <typename T> friend struct RefCountState;
|
|
|
|
/// An RCStateTransition can represent either an RC end point (i.e. an initial
|
|
/// or terminal RC transition) or a ptr set of Mutators.
|
|
ValueBase *EndPoint;
|
|
llvm::SmallPtrSet<SILInstruction *, 2> Mutators;
|
|
RCStateTransitionKind Kind;
|
|
|
|
// Should only be constructed be default RefCountState.
|
|
RCStateTransition() {}
|
|
|
|
public:
|
|
~RCStateTransition() {}
|
|
RCStateTransition(const RCStateTransition &R);
|
|
|
|
RCStateTransition(SILInstruction *I) {
|
|
Kind = getRCStateTransitionKind(I);
|
|
if (isRCStateTransitionEndPoint(Kind)) {
|
|
EndPoint = I;
|
|
return;
|
|
}
|
|
|
|
if (isRCStateTransitionMutator(Kind)) {
|
|
Mutators.insert(I);
|
|
return;
|
|
}
|
|
|
|
// Unknown kind.
|
|
}
|
|
|
|
RCStateTransition(SILArgument *A)
|
|
: EndPoint(A), Kind(RCStateTransitionKind::StrongEntrance) {
|
|
assert(A->hasConvention(ParameterConvention::Direct_Owned) &&
|
|
"Expected owned argument");
|
|
}
|
|
|
|
RCStateTransitionKind getKind() const { return Kind; }
|
|
|
|
|
|
/// Define test functions for the various abstract categorizations we have.
|
|
#define ABSTRACT_VALUE(Name, StartKind, EndKind) bool is ## Name() const;
|
|
#include "RCStateTransition.def"
|
|
|
|
/// Return true if this Transition is a mutator transition that contains I.
|
|
bool containsMutator(SILInstruction *I) const {
|
|
assert(isMutator() && "This should only be called if we are of mutator "
|
|
"kind");
|
|
return Mutators.count(I);
|
|
}
|
|
|
|
using mutator_range = Range<decltype(Mutators)::iterator>;
|
|
using const_mutator_range = Range<decltype(Mutators)::const_iterator>;
|
|
|
|
/// Returns a Range of Mutators. Asserts if this transition is not a mutator
|
|
/// transition.
|
|
mutator_range getMutators() const {
|
|
assert(isMutator() && "This should never be called given mutators");
|
|
return {Mutators.begin(), Mutators.end()};
|
|
}
|
|
|
|
/// Return true if Inst is an instruction that causes a transition that can be
|
|
/// paired with this transition.
|
|
bool matchingInst(SILInstruction *Inst) const;
|
|
|
|
/// Attempt to merge \p Other into \p this. Returns true if we succeeded,
|
|
/// false otherwise.
|
|
bool merge(const RCStateTransition &Other);
|
|
};
|
|
|
|
} // end swift namespace
|
|
|
|
namespace llvm {
|
|
raw_ostream &operator<<(raw_ostream &os, swift::RCStateTransitionKind Kind);
|
|
} // end llvm namespace
|
|
|
|
#endif
|