Files
swift-mirror/include/swift/SILAnalysis/Analysis.h
Mark Lacey 7c62b7d3b2 Coding style tweaks.
Swift SVN r27017
2015-04-05 07:12:33 +00:00

166 lines
5.5 KiB
C++

//===-- Analysis.h - Swift Analysis ----------------------------*- 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
//
//===----------------------------------------------------------------------===//
#include "llvm/Support/Casting.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
#ifndef SWIFT_SILANALYSIS_ANALYSIS_H
#define SWIFT_SILANALYSIS_ANALYSIS_H
namespace swift {
class SILModule;
class SILFunction;
class SILPassManager;
/// The base class for all SIL-level analysis.
class SILAnalysis {
public:
/// This is a list of values that allow passes to communicate to analysis
/// which traits of the code were preserved. Based on this information
/// the analysis can decide if it needs to be invalidated. This information
/// may refer to a specific function or to a list of functions depending
/// on the context in which it is used.
enum PreserveKind : unsigned {
Nothing = 0x0, // The pass does not preserve any analysis trait.
Calls = 0x1, // The pass did not modify any calls.
Branches = 0x2, // The pass did not modify any branches.
// This is a list of combined traits that is defined to make the use of
/// the invalidation API more convenient.
ProgramFlow = Calls | Branches, // The pass changed some instructions but
// did not change the overall flow
// of the code.
};
/// A list of the known analysis.
enum class AnalysisKind {
CompleteFuncs,
CallGraph,
Dominance,
PostDominance,
Alias,
LoopInfo,
IVAnalysis,
PostOrder,
ClassHierarchyAnalysis,
RCIdentity,
Destructor
};
private:
/// Stores the kind of derived class.
const AnalysisKind Kind;
/// A lock that prevents the invalidation of this analysis. When this
/// variable is set to True then the PassManager should not invalidate
/// this analysis.
bool invalidationLock;
public:
/// Returns the kind of derived class.
AnalysisKind getKind() const { return Kind; }
/// C'tor.
SILAnalysis(AnalysisKind K) : Kind(K), invalidationLock(false) {}
/// D'tor.
virtual ~SILAnalysis() {}
/// Lock the analysis. This means that invalidation messages are ignored.
void lockInvalidation() {invalidationLock = true; }
/// Unlock the analysis. This means that invalidation messages are handled.
void unlockInvalidation() {invalidationLock = false; }
/// Return True if this analysis is locked and should not be invalidated.
bool isLocked() { return invalidationLock; }
/// Invalidate all information in this analysis.
virtual void invalidate(PreserveKind K) {}
/// Invalidate all of the information for a specific function.
virtual void invalidate(SILFunction *F, PreserveKind K) {}
/// Verify the state of this analysis.
virtual void verify() const {}
};
/// An abstract base class that implements the boiler plate of cacheing and
/// invalidating analysis for specific functions.
template<typename AnalysisTy>
class FunctionAnalysisBase : public SILAnalysis {
protected:
typedef llvm::DenseMap<SILFunction *, AnalysisTy *> StorageTy;
/// Maps functions to their analysis provider.
StorageTy Storage;
/// Construct a new empty analysis for a specific function \p F.
virtual AnalysisTy *newFunctionAnalysis(SILFunction *F) = 0;
/// Return True if the analysis should be invalidated given trait \K is
/// preserved.
virtual bool shouldInvalidate(SILAnalysis::PreserveKind K) = 0;
public:
/// Returns an analysis provider for a specific function \p F.
AnalysisTy *get(SILFunction *F) {
auto &it = Storage.FindAndConstruct(F);
if (!it.second)
it.second = newFunctionAnalysis(F);
return it.second;
}
virtual void invalidate(SILAnalysis::PreserveKind K) {
if (!shouldInvalidate(K)) return;
for (auto D : Storage)
delete D.second;
Storage.clear();
}
virtual void invalidate(SILFunction *F, SILAnalysis::PreserveKind K) {
if (!shouldInvalidate(K)) return;
auto &it = Storage.FindAndConstruct(F);
if (it.second) {
delete it.second;
it.second = nullptr;
}
}
FunctionAnalysisBase(AnalysisKind K) : SILAnalysis(K), Storage() {}
FunctionAnalysisBase(const FunctionAnalysisBase &) = delete;
FunctionAnalysisBase &operator=(const FunctionAnalysisBase &) = delete;
FunctionAnalysisBase() {}
};
SILAnalysis *createCallGraphAnalysis(SILModule *M);
SILAnalysis *createAliasAnalysis(SILModule *M);
SILAnalysis *createDominanceAnalysis(SILModule *M);
SILAnalysis *createPostDominanceAnalysis(SILModule *M);
SILAnalysis *createLoopInfoAnalysis(SILModule *M, SILPassManager *PM);
SILAnalysis *createInductionVariableAnalysis(SILModule *M);
SILAnalysis *createPostOrderAnalysis(SILModule *M);
SILAnalysis *createClassHierarchyAnalysis(SILModule *M);
SILAnalysis *createRCIdentityAnalysis(SILModule *M, SILPassManager *PM);
SILAnalysis *createDestructorAnalysis(SILModule *M);
} // end namespace swift
#endif