aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/Transforms/Utils
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Transforms/Utils')
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h31
-rw-r--r--include/llvm/Transforms/Utils/BlackList.h59
-rw-r--r--include/llvm/Transforms/Utils/Local.h32
-rw-r--r--include/llvm/Transforms/Utils/ModuleUtils.h8
-rw-r--r--include/llvm/Transforms/Utils/PromoteMemToReg.h29
-rw-r--r--include/llvm/Transforms/Utils/SSAUpdater.h104
-rw-r--r--include/llvm/Transforms/Utils/SpecialCaseList.h102
7 files changed, 213 insertions, 152 deletions
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 8f1a6e2..65cafe2 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -70,28 +70,6 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL,
//
void ReplaceInstWithInst(Instruction *From, Instruction *To);
-/// FindFunctionBackedges - Analyze the specified function to find all of the
-/// loop backedges in the function and return them. This is a relatively cheap
-/// (compared to computing dominators and loop info) analysis.
-///
-/// The output is added to Result, as pairs of <from,to> edge info.
-void FindFunctionBackedges(const Function &F,
- SmallVectorImpl<std::pair<const BasicBlock*,const BasicBlock*> > &Result);
-
-
-/// GetSuccessorNumber - Search for the specified successor of basic block BB
-/// and return its position in the terminator instruction's list of
-/// successors. It is an error to call this with a block that is not a
-/// successor.
-unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ);
-
-/// isCriticalEdge - Return true if the specified edge is a critical edge.
-/// Critical edges are edges from a block with multiple successors to a block
-/// with multiple predecessors.
-///
-bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
- bool AllowIdenticalEdges = false);
-
/// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
/// split the critical edge. This will update DominatorTree and
/// DominatorFrontier information if it is available, thus calling this pass
@@ -227,6 +205,15 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp,
bool Unreachable, MDNode *BranchWeights = 0);
+///
+/// GetIfCondition - Check whether BB is the merge point of a if-region.
+/// If so, return the boolean condition that determines which entry into
+/// BB will be taken. Also, return by references the block that will be
+/// entered from if the condition is true, and the block that will be
+/// entered if the condition is false.
+
+Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue,
+ BasicBlock *&IfFalse);
} // End llvm namespace
#endif
diff --git a/include/llvm/Transforms/Utils/BlackList.h b/include/llvm/Transforms/Utils/BlackList.h
deleted file mode 100644
index 316b364..0000000
--- a/include/llvm/Transforms/Utils/BlackList.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===-- BlackList.h - blacklist for sanitizers ------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//===----------------------------------------------------------------------===//
-//
-// This is a utility class for instrumentation passes (like AddressSanitizer
-// or ThreadSanitizer) to avoid instrumenting some functions or global
-// variables based on a user-supplied blacklist.
-//
-// The blacklist disables instrumentation of various functions and global
-// variables. Each line contains a prefix, followed by a wild card expression.
-// Empty lines and lines starting with "#" are ignored.
-// ---
-// # Blacklisted items:
-// fun:*_ZN4base6subtle*
-// global:*global_with_bad_access_or_initialization*
-// global-init:*global_with_initialization_issues*
-// global-init-type:*Namespace::ClassName*
-// src:file_with_tricky_code.cc
-// global-init-src:ignore-global-initializers-issues.cc
-// ---
-// Note that the wild card is in fact an llvm::Regex, but * is automatically
-// replaced with .*
-// This is similar to the "ignore" feature of ThreadSanitizer.
-// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores
-//
-//===----------------------------------------------------------------------===//
-//
-
-#include "llvm/ADT/StringMap.h"
-
-namespace llvm {
-class Function;
-class GlobalVariable;
-class Module;
-class Regex;
-class StringRef;
-
-class BlackList {
- public:
- BlackList(const StringRef Path);
- // Returns whether either this function or it's source file are blacklisted.
- bool isIn(const Function &F) const;
- // Returns whether either this global or it's source file are blacklisted.
- bool isIn(const GlobalVariable &G) const;
- // Returns whether this module is blacklisted by filename.
- bool isIn(const Module &M) const;
- // Returns whether a global should be excluded from initialization checking.
- bool isInInit(const GlobalVariable &G) const;
- private:
- StringMap<Regex*> Entries;
-
- bool inSection(const StringRef Section, const StringRef Query) const;
-};
-
-} // namespace llvm
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 2678250..65755d0 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -39,9 +39,10 @@ class DataLayout;
class TargetLibraryInfo;
class TargetTransformInfo;
class DIBuilder;
+class AliasAnalysis;
template<typename T> class SmallVectorImpl;
-
+
//===----------------------------------------------------------------------===//
// Local constant propagation.
//
@@ -79,7 +80,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V,
/// too, recursively. Return true if a change was made.
bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0);
-
+
/// SimplifyInstructionsInBlock - Scan the specified basic block and try to
/// simplify any instructions in it and recursively delete dead instructions.
///
@@ -87,7 +88,7 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0);
/// instructions in other blocks as well in this block.
bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0,
const TargetLibraryInfo *TLI = 0);
-
+
//===----------------------------------------------------------------------===//
// Control Flow Graph Restructuring.
//
@@ -105,15 +106,15 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0,
/// recursively fold the 'and' to 0.
void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
DataLayout *TD = 0);
-
-
+
+
/// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its
/// predecessor is known to have one successor (BB!). Eliminate the edge
/// between them, moving the instructions in the predecessor into BB. This
/// deletes the predecessor block.
///
void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = 0);
-
+
/// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an
/// unconditional branch, and contains no instructions other than PHI nodes,
@@ -138,6 +139,12 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB);
bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI,
const DataLayout *TD = 0);
+/// FlatternCFG - This function is used to flatten a CFG. For
+/// example, it uses parallel-and and parallel-or mode to collapse
+// if-conditions and merge if-regions with identical statements.
+///
+bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = 0);
+
/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch,
/// and if a predecessor branches to us and one of our successors, fold the
/// setcc into the predecessor and use logical operations to pick the right
@@ -156,7 +163,7 @@ AllocaInst *DemoteRegToStack(Instruction &X,
/// DemotePHIToStack - This function takes a virtual register computed by a phi
/// node and replaces it with a slot in the stack frame, allocated via alloca.
-/// The phi node is deleted and it returns the pointer to the alloca inserted.
+/// The phi node is deleted and it returns the pointer to the alloca inserted.
AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0);
/// getOrEnforceKnownAlignment - If the specified pointer has an alignment that
@@ -179,18 +186,19 @@ static inline unsigned getKnownAlignment(Value *V, const DataLayout *TD = 0) {
template<typename IRBuilderTy>
Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP,
bool NoAssumptions = false) {
- gep_type_iterator GTI = gep_type_begin(GEP);
- Type *IntPtrTy = TD.getIntPtrType(GEP->getContext());
+ GEPOperator *GEPOp = cast<GEPOperator>(GEP);
+ Type *IntPtrTy = TD.getIntPtrType(GEP->getType());
Value *Result = Constant::getNullValue(IntPtrTy);
// If the GEP is inbounds, we know that none of the addressing operations will
// overflow in an unsigned sense.
- bool isInBounds = cast<GEPOperator>(GEP)->isInBounds() && !NoAssumptions;
+ bool isInBounds = GEPOp->isInBounds() && !NoAssumptions;
// Build a mask for high order bits.
- unsigned IntPtrWidth = TD.getPointerSizeInBits();
- uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
+ unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth();
+ uint64_t PtrSizeMask = ~0ULL >> (64 - IntPtrWidth);
+ gep_type_iterator GTI = gep_type_begin(GEP);
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
++i, ++GTI) {
Value *Op = *i;
diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h
index bb7fc06..98a19ed 100644
--- a/include/llvm/Transforms/Utils/ModuleUtils.h
+++ b/include/llvm/Transforms/Utils/ModuleUtils.h
@@ -18,6 +18,9 @@ namespace llvm {
class Module;
class Function;
+class GlobalValue;
+class GlobalVariable;
+template <class PtrType, unsigned SmallSize> class SmallPtrSet;
/// Append F to the list of global ctors of module M with the given Priority.
/// This wraps the function in the appropriate structure and stores it along
@@ -28,6 +31,11 @@ void appendToGlobalCtors(Module &M, Function *F, int Priority);
/// Same as appendToGlobalCtors(), but for global dtors.
void appendToGlobalDtors(Module &M, Function *F, int Priority);
+/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect
+/// the initializer elements of that global in Set and return the global itself.
+GlobalVariable *collectUsedGlobalVariables(Module &M,
+ SmallPtrSet<GlobalValue *, 8> &Set,
+ bool CompilerUsed);
} // End llvm namespace
#endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h
index 52a6157..2f28f33 100644
--- a/include/llvm/Transforms/Utils/PromoteMemToReg.h
+++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h
@@ -15,29 +15,34 @@
#ifndef LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H
#define LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H
-#include <vector>
+#include "llvm/ADT/ArrayRef.h"
namespace llvm {
class AllocaInst;
+class DataLayout;
class DominatorTree;
class AliasSetTracker;
-/// isAllocaPromotable - Return true if this alloca is legal for promotion.
-/// This is true if there are only loads and stores to the alloca...
+/// \brief Return true if this alloca is legal for promotion.
///
-bool isAllocaPromotable(const AllocaInst *AI);
-
-/// PromoteMemToReg - Promote the specified list of alloca instructions into
-/// scalar registers, inserting PHI nodes as appropriate. This function makes
-/// use of DominanceFrontier information. This function does not modify the CFG
-/// of the function at all. All allocas must be from the same function.
+/// This is true if there are only loads, stores, and lifetime markers
+/// (transitively) using this alloca. This also enforces that there is only
+/// ever one layer of bitcasts or GEPs between the alloca and the lifetime
+/// markers.
+bool isAllocaPromotable(const AllocaInst *AI, const DataLayout *DL);
+
+/// \brief Promote the specified list of alloca instructions into scalar
+/// registers, inserting PHI nodes as appropriate.
+///
+/// This function makes use of DominanceFrontier information. This function
+/// does not modify the CFG of the function at all. All allocas must be from
+/// the same function.
///
/// If AST is specified, the specified tracker is updated to reflect changes
/// made to the IR.
-///
-void PromoteMemToReg(const std::vector<AllocaInst*> &Allocas,
- DominatorTree &DT, AliasSetTracker *AST = 0);
+void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
+ const DataLayout *DL, AliasSetTracker *AST = 0);
} // End llvm namespace
diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h
index cd04893..0c0e5de 100644
--- a/include/llvm/Transforms/Utils/SSAUpdater.h
+++ b/include/llvm/Transforms/Utils/SSAUpdater.h
@@ -28,82 +28,90 @@ namespace llvm {
class Use;
class Value;
-/// SSAUpdater - This class updates SSA form for a set of values defined in
-/// multiple blocks. This is used when code duplication or another unstructured
+/// \brief Helper class for SSA formation on a set of values defined in
+/// multiple blocks.
+///
+/// This is used when code duplication or another unstructured
/// transformation wants to rewrite a set of uses of one value with uses of a
/// set of values.
class SSAUpdater {
friend class SSAUpdaterTraits<SSAUpdater>;
private:
- /// AvailableVals - This keeps track of which value to use on a per-block
- /// basis. When we insert PHI nodes, we keep track of them here.
+ /// This keeps track of which value to use on a per-block basis. When we
+ /// insert PHI nodes, we keep track of them here.
//typedef DenseMap<BasicBlock*, Value*> AvailableValsTy;
void *AV;
/// ProtoType holds the type of the values being rewritten.
Type *ProtoType;
- // PHI nodes are given a name based on ProtoName.
+ /// PHI nodes are given a name based on ProtoName.
std::string ProtoName;
- /// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that
- /// it creates to the vector.
+ /// If this is non-null, the SSAUpdater adds all PHI nodes that it creates to
+ /// the vector.
SmallVectorImpl<PHINode*> *InsertedPHIs;
public:
- /// SSAUpdater constructor. If InsertedPHIs is specified, it will be filled
+ /// If InsertedPHIs is specified, it will be filled
/// in with all PHI Nodes created by rewriting.
explicit SSAUpdater(SmallVectorImpl<PHINode*> *InsertedPHIs = 0);
~SSAUpdater();
- /// Initialize - Reset this object to get ready for a new set of SSA
- /// updates with type 'Ty'. PHI nodes get a name based on 'Name'.
+ /// \brief Reset this object to get ready for a new set of SSA updates with
+ /// type 'Ty'.
+ ///
+ /// PHI nodes get a name based on 'Name'.
void Initialize(Type *Ty, StringRef Name);
- /// AddAvailableValue - Indicate that a rewritten value is available at the
- /// end of the specified block with the specified value.
+ /// \brief Indicate that a rewritten value is available in the specified block
+ /// with the specified value.
void AddAvailableValue(BasicBlock *BB, Value *V);
- /// HasValueForBlock - Return true if the SSAUpdater already has a value for
- /// the specified block.
+ /// \brief Return true if the SSAUpdater already has a value for the specified
+ /// block.
bool HasValueForBlock(BasicBlock *BB) const;
- /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is
- /// live at the end of the specified block.
+ /// \brief Construct SSA form, materializing a value that is live at the end
+ /// of the specified block.
Value *GetValueAtEndOfBlock(BasicBlock *BB);
- /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that
- /// is live in the middle of the specified block.
+ /// \brief Construct SSA form, materializing a value that is live in the
+ /// middle of the specified block.
///
- /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one
- /// important case: if there is a definition of the rewritten value after the
- /// 'use' in BB. Consider code like this:
+ /// \c GetValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except
+ /// in one important case: if there is a definition of the rewritten value
+ /// after the 'use' in BB. Consider code like this:
///
+ /// \code
/// X1 = ...
/// SomeBB:
/// use(X)
/// X2 = ...
/// br Cond, SomeBB, OutBB
+ /// \endcode
///
/// In this case, there are two values (X1 and X2) added to the AvailableVals
/// set by the client of the rewriter, and those values are both live out of
/// their respective blocks. However, the use of X happens in the *middle* of
/// a block. Because of this, we need to insert a new PHI node in SomeBB to
/// merge the appropriate values, and this value isn't live out of the block.
- ///
Value *GetValueInMiddleOfBlock(BasicBlock *BB);
- /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes,
- /// which use their value in the corresponding predecessor. Note that this
- /// will not work if the use is supposed to be rewritten to a value defined in
- /// the same block as the use, but above it. Any 'AddAvailableValue's added
- /// for the use's block will be considered to be below it.
+ /// \brief Rewrite a use of the symbolic value.
+ ///
+ /// This handles PHI nodes, which use their value in the corresponding
+ /// predecessor. Note that this will not work if the use is supposed to be
+ /// rewritten to a value defined in the same block as the use, but above it.
+ /// Any 'AddAvailableValue's added for the use's block will be considered to
+ /// be below it.
void RewriteUse(Use &U);
- /// RewriteUseAfterInsertions - Rewrite a use, just like RewriteUse. However,
- /// this version of the method can rewrite uses in the same block as a
- /// definition, because it assumes that all uses of a value are below any
+ /// \brief Rewrite a use like \c RewriteUse but handling in-block definitions.
+ ///
+ /// This version of the method can rewrite uses in the same block as
+ /// a definition, because it assumes that all uses of a value are below any
/// inserted values.
void RewriteUseAfterInsertions(Use &U);
@@ -113,15 +121,15 @@ private:
void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION;
SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION;
};
-
-/// LoadAndStorePromoter - This little helper class provides a convenient way to
-/// promote a collection of loads and stores into SSA Form using the SSAUpdater.
+
+/// \brief Helper class for promoting a collection of loads and stores into SSA
+/// Form using the SSAUpdater.
+///
/// This handles complexities that SSAUpdater doesn't, such as multiple loads
/// and stores in one block.
///
/// Clients of this class are expected to subclass this and implement the
/// virtual methods.
-///
class LoadAndStorePromoter {
protected:
SSAUpdater &SSA;
@@ -130,34 +138,36 @@ public:
SSAUpdater &S, StringRef Name = StringRef());
virtual ~LoadAndStorePromoter() {}
- /// run - This does the promotion. Insts is a list of loads and stores to
- /// promote, and Name is the basename for the PHIs to insert. After this is
- /// complete, the loads and stores are removed from the code.
+ /// \brief This does the promotion.
+ ///
+ /// Insts is a list of loads and stores to promote, and Name is the basename
+ /// for the PHIs to insert. After this is complete, the loads and stores are
+ /// removed from the code.
void run(const SmallVectorImpl<Instruction*> &Insts) const;
- /// Return true if the specified instruction is in the Inst list (which was
- /// passed into the run method). Clients should implement this with a more
- /// efficient version if possible.
+ /// \brief Return true if the specified instruction is in the Inst list.
+ ///
+ /// The Insts list is the one passed into the constructor. Clients should
+ /// implement this with a more efficient version if possible.
virtual bool isInstInList(Instruction *I,
const SmallVectorImpl<Instruction*> &Insts) const;
- /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the
- /// stores are found and inserted as available values, but
+ /// \brief This hook is invoked after all the stores are found and inserted as
+ /// available values.
virtual void doExtraRewritesBeforeFinalDeletion() const {
}
- /// replaceLoadWithValue - Clients can choose to implement this to get
- /// notified right before a load is RAUW'd another value.
+ /// \brief Clients can choose to implement this to get notified right before
+ /// a load is RAUW'd another value.
virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {
}
- /// This is called before each instruction is deleted.
+ /// \brief Called before each instruction is deleted.
virtual void instructionDeleted(Instruction *I) const {
}
- /// updateDebugInfo - This is called to update debug info associated with the
- /// instruction.
+ /// \brief Called to update debug info associated with the instruction.
virtual void updateDebugInfo(Instruction *I) const {
}
};
diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h
new file mode 100644
index 0000000..787ddb0
--- /dev/null
+++ b/include/llvm/Transforms/Utils/SpecialCaseList.h
@@ -0,0 +1,102 @@
+//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//===----------------------------------------------------------------------===//
+//
+// This is a utility class for instrumentation passes (like AddressSanitizer
+// or ThreadSanitizer) to avoid instrumenting some functions or global
+// variables based on a user-supplied list.
+//
+// The list can also specify categories for specific globals, which can be used
+// to instruct an instrumentation pass to treat certain functions or global
+// variables in a specific way, such as by omitting certain aspects of
+// instrumentation while keeping others, or informing the instrumentation pass
+// that a specific uninstrumentable function has certain semantics, thus
+// allowing the pass to instrument callers according to those semantics.
+//
+// For example, AddressSanitizer uses the "init" category for globals whose
+// initializers should not be instrumented, but which in all other respects
+// should be instrumented.
+//
+// Each line contains a prefix, followed by a colon and a wild card expression,
+// followed optionally by an equals sign and an instrumentation-specific
+// category. Empty lines and lines starting with "#" are ignored.
+// ---
+// # Blacklisted items:
+// fun:*_ZN4base6subtle*
+// global:*global_with_bad_access_or_initialization*
+// global:*global_with_initialization_issues*=init
+// type:*Namespace::ClassName*=init
+// src:file_with_tricky_code.cc
+// src:ignore-global-initializers-issues.cc=init
+//
+// # Functions with pure functional semantics:
+// fun:cos=functional
+// fun:sin=functional
+// ---
+// Note that the wild card is in fact an llvm::Regex, but * is automatically
+// replaced with .*
+// This is similar to the "ignore" feature of ThreadSanitizer.
+// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores
+//
+//===----------------------------------------------------------------------===//
+//
+
+#include "llvm/ADT/StringMap.h"
+
+namespace llvm {
+class Function;
+class GlobalVariable;
+class MemoryBuffer;
+class Module;
+class Regex;
+class StringRef;
+
+class SpecialCaseList {
+ public:
+ SpecialCaseList(const StringRef Path);
+ SpecialCaseList(const MemoryBuffer *MB);
+ ~SpecialCaseList();
+
+ /// Returns whether either this function or its source file are listed in the
+ /// given category, which may be omitted to search the empty category.
+ bool isIn(const Function &F, const StringRef Category = StringRef()) const;
+
+ /// Returns whether this global, its type or its source file are listed in the
+ /// given category, which may be omitted to search the empty category.
+ bool isIn(const GlobalVariable &G,
+ const StringRef Category = StringRef()) const;
+
+ /// Returns whether this module is listed in the given category, which may be
+ /// omitted to search the empty category.
+ bool isIn(const Module &M, const StringRef Category = StringRef()) const;
+
+ /// Returns whether either this function or its source file are listed in any
+ /// category. Category will contain the name of an arbitrary category in
+ /// which this function is listed.
+ bool findCategory(const Function &F, StringRef &Category) const;
+
+ /// Returns whether this global, its type or its source file are listed in any
+ /// category. Category will contain the name of an arbitrary category in
+ /// which this global is listed.
+ bool findCategory(const GlobalVariable &G, StringRef &Category) const;
+
+ /// Returns whether this module is listed in any category. Category will
+ /// contain the name of an arbitrary category in which this module is listed.
+ bool findCategory(const Module &M, StringRef &Category) const;
+
+ private:
+ struct Entry;
+ StringMap<StringMap<Entry> > Entries;
+
+ void init(const MemoryBuffer *MB);
+ bool findCategory(const StringRef Section, const StringRef Query,
+ StringRef &Category) const;
+ bool inSectionCategory(const StringRef Section, const StringRef Query,
+ const StringRef Category) const;
+};
+
+} // namespace llvm