mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-08 13:26:19 +00:00
IR: Create SymbolTableList wrapper around iplist, NFC
Create `SymbolTableList`, a wrapper around `iplist` for lists that automatically manage a symbol table. This commit reduces a ton of code duplication between the six traits classes that were used previously. As a drive by, reduce the number of template parameters from 2 to 1 by using a SymbolTableListParentType metafunction (I originally had this as a separate commit, but it touched most of the same lines so I squashed them). I'm in the process of trying to remove the UB in `createSentinel()` (see the FIXMEs I added for `ilist_embedded_sentinel_traits` and `ilist_half_embedded_sentinel_traits`). My eventual goal is to separate the list logic into a base class layer that knows nothing about (and isn't templated on) the downcasted nodes -- removing the need to invoke UB -- but for now I'm just trying to get a handle on all the current use cases (and cleaning things up as I see them). Besides these six SymbolTable lists, there are two others that use the addNode/removeNode/transferNodes() hooks: the `MachineInstruction` and `MachineBasicBlock` lists. Ideally there'll be a way to factor these hooks out of the low-level API entirely, but I'm not quite there yet. llvm-svn: 249602
This commit is contained in:
parent
f6945cd657
commit
d8033eebd6
@ -104,6 +104,53 @@ struct ilist_sentinel_traits {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename NodeTy> class ilist_half_node;
|
||||
template <typename NodeTy> class ilist_node;
|
||||
|
||||
/// Traits with an embedded ilist_node as a sentinel.
|
||||
///
|
||||
/// FIXME: The downcast in createSentinel() is UB.
|
||||
template <typename NodeTy> struct ilist_embedded_sentinel_traits {
|
||||
/// Get hold of the node that marks the end of the list.
|
||||
NodeTy *createSentinel() const {
|
||||
// Since i(p)lists always publicly derive from their corresponding traits,
|
||||
// placing a data member in this class will augment the i(p)list. But since
|
||||
// the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,
|
||||
// there is a legal viable downcast from it to NodeTy. We use this trick to
|
||||
// superimpose an i(p)list with a "ghostly" NodeTy, which becomes the
|
||||
// sentinel. Dereferencing the sentinel is forbidden (save the
|
||||
// ilist_node<NodeTy>), so no one will ever notice the superposition.
|
||||
return static_cast<NodeTy *>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(NodeTy *) {}
|
||||
|
||||
NodeTy *provideInitialHead() const { return createSentinel(); }
|
||||
NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }
|
||||
static void noteHead(NodeTy *, NodeTy *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<NodeTy> Sentinel;
|
||||
};
|
||||
|
||||
/// Trait with an embedded ilist_half_node as a sentinel.
|
||||
///
|
||||
/// FIXME: The downcast in createSentinel() is UB.
|
||||
template <typename NodeTy> struct ilist_half_embedded_sentinel_traits {
|
||||
/// Get hold of the node that marks the end of the list.
|
||||
NodeTy *createSentinel() const {
|
||||
// See comment in ilist_embedded_sentinel_traits::createSentinel().
|
||||
return static_cast<NodeTy *>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(NodeTy *) {}
|
||||
|
||||
NodeTy *provideInitialHead() const { return createSentinel(); }
|
||||
NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }
|
||||
static void noteHead(NodeTy *, NodeTy *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_half_node<NodeTy> Sentinel;
|
||||
};
|
||||
|
||||
/// ilist_node_traits - A fragment for template traits for intrusive list
|
||||
/// that provides default node related operations.
|
||||
///
|
||||
|
@ -19,12 +19,15 @@ namespace llvm {
|
||||
|
||||
template<typename NodeTy>
|
||||
struct ilist_traits;
|
||||
template <typename NodeTy> struct ilist_embedded_sentinel_traits;
|
||||
template <typename NodeTy> struct ilist_half_embedded_sentinel_traits;
|
||||
|
||||
/// ilist_half_node - Base class that provides prev services for sentinels.
|
||||
///
|
||||
template<typename NodeTy>
|
||||
class ilist_half_node {
|
||||
friend struct ilist_traits<NodeTy>;
|
||||
friend struct ilist_half_embedded_sentinel_traits<NodeTy>;
|
||||
NodeTy *Prev;
|
||||
protected:
|
||||
NodeTy *getPrev() { return Prev; }
|
||||
@ -43,6 +46,8 @@ template<typename NodeTy>
|
||||
class ilist_node : private ilist_half_node<NodeTy> {
|
||||
friend struct ilist_nextprev_traits<NodeTy>;
|
||||
friend struct ilist_traits<NodeTy>;
|
||||
friend struct ilist_half_embedded_sentinel_traits<NodeTy>;
|
||||
friend struct ilist_embedded_sentinel_traits<NodeTy>;
|
||||
NodeTy *Next;
|
||||
NodeTy *getNext() { return Next; }
|
||||
const NodeTy *getNext() const { return Next; }
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits;
|
||||
template <typename NodeTy> class SymbolTableListTraits;
|
||||
|
||||
/// \brief LLVM Argument representation
|
||||
///
|
||||
@ -36,7 +35,7 @@ class Argument : public Value, public ilist_node<Argument> {
|
||||
virtual void anchor();
|
||||
Function *Parent;
|
||||
|
||||
friend class SymbolTableListTraits<Argument, Function>;
|
||||
friend class SymbolTableListTraits<Argument>;
|
||||
void setParent(Function *parent);
|
||||
|
||||
public:
|
||||
|
@ -30,20 +30,9 @@ class LLVMContext;
|
||||
class BlockAddress;
|
||||
class Function;
|
||||
|
||||
// Traits for intrusive list of basic blocks...
|
||||
template<> struct ilist_traits<BasicBlock>
|
||||
: public SymbolTableListTraits<BasicBlock, Function> {
|
||||
|
||||
BasicBlock *createSentinel() const;
|
||||
static void destroySentinel(BasicBlock*) {}
|
||||
|
||||
BasicBlock *provideInitialHead() const { return createSentinel(); }
|
||||
BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
|
||||
static void noteHead(BasicBlock*, BasicBlock*) {}
|
||||
private:
|
||||
mutable ilist_half_node<BasicBlock> Sentinel;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct SymbolTableListSentinelTraits<BasicBlock>
|
||||
: public ilist_half_embedded_sentinel_traits<BasicBlock> {};
|
||||
|
||||
/// \brief LLVM Basic Block Representation
|
||||
///
|
||||
@ -64,13 +53,14 @@ class BasicBlock : public Value, // Basic blocks are data objects also
|
||||
public ilist_node<BasicBlock> {
|
||||
friend class BlockAddress;
|
||||
public:
|
||||
typedef iplist<Instruction> InstListType;
|
||||
typedef SymbolTableList<Instruction> InstListType;
|
||||
|
||||
private:
|
||||
InstListType InstList;
|
||||
Function *Parent;
|
||||
|
||||
void setParent(Function *parent);
|
||||
friend class SymbolTableListTraits<BasicBlock, Function>;
|
||||
friend class SymbolTableListTraits<BasicBlock>;
|
||||
|
||||
BasicBlock(const BasicBlock &) = delete;
|
||||
void operator=(const BasicBlock &) = delete;
|
||||
@ -169,7 +159,7 @@ public:
|
||||
/// \brief Unlink 'this' from the containing function and delete it.
|
||||
///
|
||||
// \returns an iterator pointing to the element after the erased one.
|
||||
iplist<BasicBlock>::iterator eraseFromParent();
|
||||
SymbolTableList<BasicBlock>::iterator eraseFromParent();
|
||||
|
||||
/// \brief Unlink this basic block from its current function and insert it
|
||||
/// into the function that \p MovePos lives in, right before \p MovePos.
|
||||
@ -340,12 +330,6 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const {
|
||||
return static_cast<BasicBlock*>(&Sentinel);
|
||||
}
|
||||
|
||||
// Create wrappers for C Binding types (see CBindingWrapping.h).
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
|
||||
|
||||
|
@ -34,26 +34,14 @@ class FunctionType;
|
||||
class LLVMContext;
|
||||
class DISubprogram;
|
||||
|
||||
template<> struct ilist_traits<Argument>
|
||||
: public SymbolTableListTraits<Argument, Function> {
|
||||
|
||||
Argument *createSentinel() const {
|
||||
return static_cast<Argument*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(Argument*) {}
|
||||
|
||||
Argument *provideInitialHead() const { return createSentinel(); }
|
||||
Argument *ensureHead(Argument*) const { return createSentinel(); }
|
||||
static void noteHead(Argument*, Argument*) {}
|
||||
|
||||
private:
|
||||
mutable ilist_half_node<Argument> Sentinel;
|
||||
};
|
||||
template <>
|
||||
struct SymbolTableListSentinelTraits<Argument>
|
||||
: public ilist_half_embedded_sentinel_traits<Argument> {};
|
||||
|
||||
class Function : public GlobalObject, public ilist_node<Function> {
|
||||
public:
|
||||
typedef iplist<Argument> ArgumentListType;
|
||||
typedef iplist<BasicBlock> BasicBlockListType;
|
||||
typedef SymbolTableList<Argument> ArgumentListType;
|
||||
typedef SymbolTableList<BasicBlock> BasicBlockListType;
|
||||
|
||||
// BasicBlock iterators...
|
||||
typedef BasicBlockListType::iterator iterator;
|
||||
@ -90,7 +78,7 @@ private:
|
||||
(Value ? Mask : 0u));
|
||||
}
|
||||
|
||||
friend class SymbolTableListTraits<Function, Module>;
|
||||
friend class SymbolTableListTraits<Function>;
|
||||
|
||||
void setParent(Module *parent);
|
||||
|
||||
|
@ -23,11 +23,10 @@
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits;
|
||||
template <typename ValueSubClass> class SymbolTableListTraits;
|
||||
|
||||
class GlobalAlias : public GlobalValue, public ilist_node<GlobalAlias> {
|
||||
friend class SymbolTableListTraits<GlobalAlias, Module>;
|
||||
friend class SymbolTableListTraits<GlobalAlias>;
|
||||
void operator=(const GlobalAlias &) = delete;
|
||||
GlobalAlias(const GlobalAlias &) = delete;
|
||||
|
||||
|
@ -29,11 +29,10 @@ namespace llvm {
|
||||
|
||||
class Module;
|
||||
class Constant;
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits;
|
||||
template <typename ValueSubClass> class SymbolTableListTraits;
|
||||
|
||||
class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
|
||||
friend class SymbolTableListTraits<GlobalVariable, Module>;
|
||||
friend class SymbolTableListTraits<GlobalVariable>;
|
||||
void *operator new(size_t, unsigned) = delete;
|
||||
void operator=(const GlobalVariable &) = delete;
|
||||
GlobalVariable(const GlobalVariable &) = delete;
|
||||
|
@ -115,13 +115,10 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef InstIterator<iplist<BasicBlock>,
|
||||
Function::iterator, BasicBlock::iterator,
|
||||
Instruction> inst_iterator;
|
||||
typedef InstIterator<const iplist<BasicBlock>,
|
||||
Function::const_iterator,
|
||||
BasicBlock::const_iterator,
|
||||
typedef InstIterator<SymbolTableList<BasicBlock>, Function::iterator,
|
||||
BasicBlock::iterator, Instruction> inst_iterator;
|
||||
typedef InstIterator<const SymbolTableList<BasicBlock>,
|
||||
Function::const_iterator, BasicBlock::const_iterator,
|
||||
const Instruction> const_inst_iterator;
|
||||
typedef iterator_range<inst_iterator> inst_range;
|
||||
typedef iterator_range<const_inst_iterator> const_inst_range;
|
||||
|
@ -30,23 +30,8 @@ class BasicBlock;
|
||||
struct AAMDNodes;
|
||||
|
||||
template <>
|
||||
struct ilist_traits<Instruction>
|
||||
: public SymbolTableListTraits<Instruction, BasicBlock> {
|
||||
|
||||
/// \brief Return a node that marks the end of a list.
|
||||
///
|
||||
/// The sentinel is relative to this instance, so we use a non-static
|
||||
/// method.
|
||||
Instruction *createSentinel() const;
|
||||
static void destroySentinel(Instruction *) {}
|
||||
|
||||
Instruction *provideInitialHead() const { return createSentinel(); }
|
||||
Instruction *ensureHead(Instruction *) const { return createSentinel(); }
|
||||
static void noteHead(Instruction *, Instruction *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_half_node<Instruction> Sentinel;
|
||||
};
|
||||
struct SymbolTableListSentinelTraits<Instruction>
|
||||
: public ilist_half_embedded_sentinel_traits<Instruction> {};
|
||||
|
||||
class Instruction : public User, public ilist_node<Instruction> {
|
||||
void operator=(const Instruction &) = delete;
|
||||
@ -89,7 +74,7 @@ public:
|
||||
/// block and deletes it.
|
||||
///
|
||||
/// \returns an iterator pointing to the element after the erased one
|
||||
iplist<Instruction>::iterator eraseFromParent();
|
||||
SymbolTableList<Instruction>::iterator eraseFromParent();
|
||||
|
||||
/// Insert an unlinked instruction into a basic block immediately before
|
||||
/// the specified instruction.
|
||||
@ -506,7 +491,7 @@ private:
|
||||
(V ? HasMetadataBit : 0));
|
||||
}
|
||||
|
||||
friend class SymbolTableListTraits<Instruction, BasicBlock>;
|
||||
friend class SymbolTableListTraits<Instruction>;
|
||||
void setParent(BasicBlock *P);
|
||||
protected:
|
||||
// Instruction subclasses can stick up to 15 bits of stuff into the
|
||||
@ -532,17 +517,6 @@ private:
|
||||
Instruction *cloneImpl() const;
|
||||
};
|
||||
|
||||
inline Instruction *ilist_traits<Instruction>::createSentinel() const {
|
||||
// Since i(p)lists always publicly derive from their corresponding traits,
|
||||
// placing a data member in this class will augment the i(p)list. But since
|
||||
// the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,
|
||||
// there is a legal viable downcast from it to NodeTy. We use this trick to
|
||||
// superimpose an i(p)list with a "ghostly" NodeTy, which becomes the
|
||||
// sentinel. Dereferencing the sentinel is forbidden (save the
|
||||
// ilist_node<NodeTy>), so no one will ever notice the superposition.
|
||||
return static_cast<Instruction *>(&Sentinel);
|
||||
}
|
||||
|
||||
// Instruction* is only 4-byte aligned.
|
||||
template<>
|
||||
class PointerLikeTypeTraits<Instruction*> {
|
||||
|
@ -32,9 +32,6 @@ class LLVMContext;
|
||||
class Module;
|
||||
class ModuleSlotTracker;
|
||||
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits;
|
||||
|
||||
enum LLVMConstants : uint32_t {
|
||||
DEBUG_METADATA_VERSION = 3 // Current debug info version number.
|
||||
};
|
||||
@ -1129,7 +1126,6 @@ public:
|
||||
///
|
||||
/// TODO: Inherit from Metadata.
|
||||
class NamedMDNode : public ilist_node<NamedMDNode> {
|
||||
friend class SymbolTableListTraits<NamedMDNode, Module>;
|
||||
friend struct ilist_traits<NamedMDNode>;
|
||||
friend class LLVMContextImpl;
|
||||
friend class Module;
|
||||
|
@ -34,58 +34,6 @@ class LLVMContext;
|
||||
class RandomNumberGenerator;
|
||||
class StructType;
|
||||
|
||||
template<> struct ilist_traits<Function>
|
||||
: public SymbolTableListTraits<Function, Module> {
|
||||
|
||||
// createSentinel is used to get hold of the node that marks the end of the
|
||||
// list... (same trick used here as in ilist_traits<Instruction>)
|
||||
Function *createSentinel() const {
|
||||
return static_cast<Function*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(Function*) {}
|
||||
|
||||
Function *provideInitialHead() const { return createSentinel(); }
|
||||
Function *ensureHead(Function*) const { return createSentinel(); }
|
||||
static void noteHead(Function*, Function*) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<Function> Sentinel;
|
||||
};
|
||||
|
||||
template<> struct ilist_traits<GlobalVariable>
|
||||
: public SymbolTableListTraits<GlobalVariable, Module> {
|
||||
// createSentinel is used to create a node that marks the end of the list.
|
||||
GlobalVariable *createSentinel() const {
|
||||
return static_cast<GlobalVariable*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(GlobalVariable*) {}
|
||||
|
||||
GlobalVariable *provideInitialHead() const { return createSentinel(); }
|
||||
GlobalVariable *ensureHead(GlobalVariable *) const {
|
||||
return createSentinel();
|
||||
}
|
||||
static void noteHead(GlobalVariable *, GlobalVariable *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<GlobalVariable> Sentinel;
|
||||
};
|
||||
|
||||
template<> struct ilist_traits<GlobalAlias>
|
||||
: public SymbolTableListTraits<GlobalAlias, Module> {
|
||||
// createSentinel is used to create a node that marks the end of the list.
|
||||
GlobalAlias *createSentinel() const {
|
||||
return static_cast<GlobalAlias*>(&Sentinel);
|
||||
}
|
||||
static void destroySentinel(GlobalAlias*) {}
|
||||
|
||||
GlobalAlias *provideInitialHead() const { return createSentinel(); }
|
||||
GlobalAlias *ensureHead(GlobalAlias *) const { return createSentinel(); }
|
||||
static void noteHead(GlobalAlias *, GlobalAlias *) {}
|
||||
|
||||
private:
|
||||
mutable ilist_node<GlobalAlias> Sentinel;
|
||||
};
|
||||
|
||||
template<> struct ilist_traits<NamedMDNode>
|
||||
: public ilist_default_traits<NamedMDNode> {
|
||||
// createSentinel is used to get hold of a node that marks the end of
|
||||
@ -121,11 +69,11 @@ class Module {
|
||||
/// @{
|
||||
public:
|
||||
/// The type for the list of global variables.
|
||||
typedef iplist<GlobalVariable> GlobalListType;
|
||||
typedef SymbolTableList<GlobalVariable> GlobalListType;
|
||||
/// The type for the list of functions.
|
||||
typedef iplist<Function> FunctionListType;
|
||||
typedef SymbolTableList<Function> FunctionListType;
|
||||
/// The type for the list of aliases.
|
||||
typedef iplist<GlobalAlias> AliasListType;
|
||||
typedef SymbolTableList<GlobalAlias> AliasListType;
|
||||
/// The type for the list of named metadata.
|
||||
typedef ilist<NamedMDNode> NamedMDListType;
|
||||
/// The type of the comdat "symbol" table.
|
||||
|
@ -34,11 +34,46 @@ template <typename NodeTy> class ilist_iterator;
|
||||
template <typename NodeTy, typename Traits> class iplist;
|
||||
template <typename Ty> struct ilist_traits;
|
||||
|
||||
template <typename NodeTy>
|
||||
struct SymbolTableListSentinelTraits
|
||||
: public ilist_embedded_sentinel_traits<NodeTy> {};
|
||||
|
||||
/// Template metafunction to get the parent type for a symbol table list.
|
||||
///
|
||||
/// Implementations create a typedef called \c type so that we only need a
|
||||
/// single template parameter for the list and traits.
|
||||
template <typename NodeTy> struct SymbolTableListParentType {};
|
||||
class Argument;
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class GlobalVariable;
|
||||
class GlobalAlias;
|
||||
class Module;
|
||||
#define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
|
||||
template <> struct SymbolTableListParentType<NODE> { typedef PARENT type; };
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function)
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function)
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
|
||||
DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
|
||||
#undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
|
||||
|
||||
template <typename NodeTy> class SymbolTableList;
|
||||
|
||||
// ValueSubClass - The type of objects that I hold, e.g. Instruction.
|
||||
// ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
|
||||
//
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits : public ilist_default_traits<ValueSubClass> {
|
||||
template <typename ValueSubClass>
|
||||
class SymbolTableListTraits
|
||||
: public ilist_nextprev_traits<ValueSubClass>,
|
||||
public SymbolTableListSentinelTraits<ValueSubClass>,
|
||||
public ilist_node_traits<ValueSubClass> {
|
||||
typedef SymbolTableList<ValueSubClass> ListTy;
|
||||
typedef
|
||||
typename SymbolTableListParentType<ValueSubClass>::type ItemParentClass;
|
||||
|
||||
public:
|
||||
SymbolTableListTraits() {}
|
||||
|
||||
@ -48,12 +83,12 @@ private:
|
||||
ItemParentClass *getListOwner() {
|
||||
size_t Offset(size_t(&((ItemParentClass*)nullptr->*ItemParentClass::
|
||||
getSublistAccess(static_cast<ValueSubClass*>(nullptr)))));
|
||||
iplist<ValueSubClass>* Anchor(static_cast<iplist<ValueSubClass>*>(this));
|
||||
ListTy *Anchor(static_cast<ListTy *>(this));
|
||||
return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)-
|
||||
Offset);
|
||||
}
|
||||
|
||||
static iplist<ValueSubClass> &getList(ItemParentClass *Par) {
|
||||
static ListTy &getList(ItemParentClass *Par) {
|
||||
return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr));
|
||||
}
|
||||
|
||||
@ -64,7 +99,7 @@ private:
|
||||
public:
|
||||
void addNodeToList(ValueSubClass *V);
|
||||
void removeNodeFromList(ValueSubClass *V);
|
||||
void transferNodesFromList(ilist_traits<ValueSubClass> &L2,
|
||||
void transferNodesFromList(SymbolTableListTraits &L2,
|
||||
ilist_iterator<ValueSubClass> first,
|
||||
ilist_iterator<ValueSubClass> last);
|
||||
//private:
|
||||
@ -74,6 +109,14 @@ public:
|
||||
static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; }
|
||||
};
|
||||
|
||||
/// List that automatically updates parent links and symbol tables.
|
||||
///
|
||||
/// When nodes are inserted into and removed from this list, the associated
|
||||
/// symbol table will be automatically updated. Similarly, parent links get
|
||||
/// updated automatically.
|
||||
template <typename NodeTy>
|
||||
class SymbolTableList : public iplist<NodeTy, SymbolTableListTraits<NodeTy>> {};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -19,8 +19,7 @@
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
class SymbolTableListTraits;
|
||||
template <typename ValueSubClass> class SymbolTableListTraits;
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class NamedMDNode;
|
||||
@ -33,12 +32,12 @@ namespace llvm {
|
||||
///
|
||||
class ValueSymbolTable {
|
||||
friend class Value;
|
||||
friend class SymbolTableListTraits<Argument, Function>;
|
||||
friend class SymbolTableListTraits<BasicBlock, Function>;
|
||||
friend class SymbolTableListTraits<Instruction, BasicBlock>;
|
||||
friend class SymbolTableListTraits<Function, Module>;
|
||||
friend class SymbolTableListTraits<GlobalVariable, Module>;
|
||||
friend class SymbolTableListTraits<GlobalAlias, Module>;
|
||||
friend class SymbolTableListTraits<Argument>;
|
||||
friend class SymbolTableListTraits<BasicBlock>;
|
||||
friend class SymbolTableListTraits<Instruction>;
|
||||
friend class SymbolTableListTraits<Function>;
|
||||
friend class SymbolTableListTraits<GlobalVariable>;
|
||||
friend class SymbolTableListTraits<GlobalAlias>;
|
||||
/// @name Types
|
||||
/// @{
|
||||
public:
|
||||
|
@ -36,7 +36,7 @@ LLVMContext &BasicBlock::getContext() const {
|
||||
|
||||
// Explicit instantiation of SymbolTableListTraits since some of the methods
|
||||
// are not in the public header file...
|
||||
template class llvm::SymbolTableListTraits<Instruction, BasicBlock>;
|
||||
template class llvm::SymbolTableListTraits<Instruction>;
|
||||
|
||||
BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
|
||||
BasicBlock *InsertBefore)
|
||||
|
@ -35,8 +35,8 @@ using namespace llvm;
|
||||
|
||||
// Explicit instantiations of SymbolTableListTraits since some of the methods
|
||||
// are not in the public header file...
|
||||
template class llvm::SymbolTableListTraits<Argument, Function>;
|
||||
template class llvm::SymbolTableListTraits<BasicBlock, Function>;
|
||||
template class llvm::SymbolTableListTraits<Argument>;
|
||||
template class llvm::SymbolTableListTraits<BasicBlock>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Argument Implementation
|
||||
|
@ -38,9 +38,9 @@ using namespace llvm;
|
||||
|
||||
// Explicit instantiations of SymbolTableListTraits since some of the methods
|
||||
// are not in the public header file.
|
||||
template class llvm::SymbolTableListTraits<Function, Module>;
|
||||
template class llvm::SymbolTableListTraits<GlobalVariable, Module>;
|
||||
template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
|
||||
template class llvm::SymbolTableListTraits<Function>;
|
||||
template class llvm::SymbolTableListTraits<GlobalVariable>;
|
||||
template class llvm::SymbolTableListTraits<GlobalAlias>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Primitive Module methods.
|
||||
|
@ -24,10 +24,10 @@ namespace llvm {
|
||||
/// setSymTabObject - This is called when (f.e.) the parent of a basic block
|
||||
/// changes. This requires us to remove all the instruction symtab entries from
|
||||
/// the current function and reinsert them into the new function.
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
template<typename TPtr>
|
||||
void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
::setSymTabObject(TPtr *Dest, TPtr Src) {
|
||||
template <typename ValueSubClass>
|
||||
template <typename TPtr>
|
||||
void SymbolTableListTraits<ValueSubClass>::setSymTabObject(TPtr *Dest,
|
||||
TPtr Src) {
|
||||
// Get the old symtab and value list before doing the assignment.
|
||||
ValueSymbolTable *OldST = getSymTab(getListOwner());
|
||||
|
||||
@ -41,7 +41,7 @@ void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
if (OldST == NewST) return;
|
||||
|
||||
// Move all the elements from the old symtab to the new one.
|
||||
iplist<ValueSubClass> &ItemList = getList(getListOwner());
|
||||
ListTy &ItemList = getList(getListOwner());
|
||||
if (ItemList.empty()) return;
|
||||
|
||||
if (OldST) {
|
||||
@ -60,9 +60,8 @@ void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
|
||||
}
|
||||
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
::addNodeToList(ValueSubClass *V) {
|
||||
template <typename ValueSubClass>
|
||||
void SymbolTableListTraits<ValueSubClass>::addNodeToList(ValueSubClass *V) {
|
||||
assert(!V->getParent() && "Value already in a container!!");
|
||||
ItemParentClass *Owner = getListOwner();
|
||||
V->setParent(Owner);
|
||||
@ -71,20 +70,19 @@ void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
ST->reinsertValue(V);
|
||||
}
|
||||
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
::removeNodeFromList(ValueSubClass *V) {
|
||||
template <typename ValueSubClass>
|
||||
void SymbolTableListTraits<ValueSubClass>::removeNodeFromList(
|
||||
ValueSubClass *V) {
|
||||
V->setParent(nullptr);
|
||||
if (V->hasName())
|
||||
if (ValueSymbolTable *ST = getSymTab(getListOwner()))
|
||||
ST->removeValueName(V->getValueName());
|
||||
}
|
||||
|
||||
template<typename ValueSubClass, typename ItemParentClass>
|
||||
void SymbolTableListTraits<ValueSubClass,ItemParentClass>
|
||||
::transferNodesFromList(ilist_traits<ValueSubClass> &L2,
|
||||
ilist_iterator<ValueSubClass> first,
|
||||
ilist_iterator<ValueSubClass> last) {
|
||||
template <typename ValueSubClass>
|
||||
void SymbolTableListTraits<ValueSubClass>::transferNodesFromList(
|
||||
SymbolTableListTraits &L2, ilist_iterator<ValueSubClass> first,
|
||||
ilist_iterator<ValueSubClass> last) {
|
||||
// We only have to do work here if transferring instructions between BBs
|
||||
ItemParentClass *NewIP = getListOwner(), *OldIP = L2.getListOwner();
|
||||
if (NewIP == OldIP) return; // No work to do at all...
|
||||
|
Loading…
x
Reference in New Issue
Block a user