llvm.org GIT mirror llvm / 2a8bcfa
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249602 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 4 years ago
17 changed file(s) with 157 addition(s) and 181 deletion(s). Raw diff Collapse all Expand all
101101 static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) {
102102 ilist_traits::setPrev(NewHead, Sentinel);
103103 }
104 };
105
106 template class ilist_half_node;
107 template class ilist_node;
108
109 /// Traits with an embedded ilist_node as a sentinel.
110 ///
111 /// FIXME: The downcast in createSentinel() is UB.
112 template struct ilist_embedded_sentinel_traits {
113 /// Get hold of the node that marks the end of the list.
114 NodeTy *createSentinel() const {
115 // Since i(p)lists always publicly derive from their corresponding traits,
116 // placing a data member in this class will augment the i(p)list. But since
117 // the NodeTy is expected to be publicly derive from ilist_node,
118 // there is a legal viable downcast from it to NodeTy. We use this trick to
119 // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the
120 // sentinel. Dereferencing the sentinel is forbidden (save the
121 // ilist_node), so no one will ever notice the superposition.
122 return static_cast(&Sentinel);
123 }
124 static void destroySentinel(NodeTy *) {}
125
126 NodeTy *provideInitialHead() const { return createSentinel(); }
127 NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }
128 static void noteHead(NodeTy *, NodeTy *) {}
129
130 private:
131 mutable ilist_node Sentinel;
132 };
133
134 /// Trait with an embedded ilist_half_node as a sentinel.
135 ///
136 /// FIXME: The downcast in createSentinel() is UB.
137 template struct ilist_half_embedded_sentinel_traits {
138 /// Get hold of the node that marks the end of the list.
139 NodeTy *createSentinel() const {
140 // See comment in ilist_embedded_sentinel_traits::createSentinel().
141 return static_cast(&Sentinel);
142 }
143 static void destroySentinel(NodeTy *) {}
144
145 NodeTy *provideInitialHead() const { return createSentinel(); }
146 NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }
147 static void noteHead(NodeTy *, NodeTy *) {}
148
149 private:
150 mutable ilist_half_node Sentinel;
104151 };
105152
106153 /// ilist_node_traits - A fragment for template traits for intrusive list
1818
1919 template
2020 struct ilist_traits;
21 template struct ilist_embedded_sentinel_traits;
22 template struct ilist_half_embedded_sentinel_traits;
2123
2224 /// ilist_half_node - Base class that provides prev services for sentinels.
2325 ///
2426 template
2527 class ilist_half_node {
2628 friend struct ilist_traits;
29 friend struct ilist_half_embedded_sentinel_traits;
2730 NodeTy *Prev;
2831 protected:
2932 NodeTy *getPrev() { return Prev; }
4245 class ilist_node : private ilist_half_node {
4346 friend struct ilist_nextprev_traits;
4447 friend struct ilist_traits;
48 friend struct ilist_half_embedded_sentinel_traits;
49 friend struct ilist_embedded_sentinel_traits;
4550 NodeTy *Next;
4651 NodeTy *getNext() { return Next; }
4752 const NodeTy *getNext() const { return Next; }
2020
2121 namespace llvm {
2222
23 template
24 class SymbolTableListTraits;
23 template class SymbolTableListTraits;
2524
2625 /// \brief LLVM Argument representation
2726 ///
3534 virtual void anchor();
3635 Function *Parent;
3736
38 friend class SymbolTableListTraits, Function>;
37 friend class SymbolTableListTraits>;
3938 void setParent(Function *parent);
4039
4140 public:
2929 class BlockAddress;
3030 class Function;
3131
32 // Traits for intrusive list of basic blocks...
33 template<> struct ilist_traits
34 : public SymbolTableListTraits {
35
36 BasicBlock *createSentinel() const;
37 static void destroySentinel(BasicBlock*) {}
38
39 BasicBlock *provideInitialHead() const { return createSentinel(); }
40 BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
41 static void noteHead(BasicBlock*, BasicBlock*) {}
42 private:
43 mutable ilist_half_node Sentinel;
44 };
45
32 template <>
33 struct SymbolTableListSentinelTraits
34 : public ilist_half_embedded_sentinel_traits {};
4635
4736 /// \brief LLVM Basic Block Representation
4837 ///
6352 public ilist_node {
6453 friend class BlockAddress;
6554 public:
66 typedef iplist InstListType;
55 typedef SymbolTableList InstListType;
56
6757 private:
6858 InstListType InstList;
6959 Function *Parent;
7060
7161 void setParent(Function *parent);
72 friend class SymbolTableListTraits, Function>;
62 friend class SymbolTableListTraits>;
7363
7464 BasicBlock(const BasicBlock &) = delete;
7565 void operator=(const BasicBlock &) = delete;
168158 /// \brief Unlink 'this' from the containing function and delete it.
169159 ///
170160 // \returns an iterator pointing to the element after the erased one.
171 iplist::iterator eraseFromParent();
161 SymbolTableList::iterator eraseFromParent();
172162
173163 /// \brief Unlink this basic block from its current function and insert it
174164 /// into the function that \p MovePos lives in, right before \p MovePos.
339329 }
340330 };
341331
342 // createSentinel is used to get hold of the node that marks the end of the
343 // list... (same trick used here as in ilist_traits)
344 inline BasicBlock *ilist_traits::createSentinel() const {
345 return static_cast(&Sentinel);
346 }
347
348332 // Create wrappers for C Binding types (see CBindingWrapping.h).
349333 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef)
350334
3333 class LLVMContext;
3434 class DISubprogram;
3535
36 template<> struct ilist_traits
37 : public SymbolTableListTraits {
38
39 Argument *createSentinel() const {
40 return static_cast(&Sentinel);
41 }
42 static void destroySentinel(Argument*) {}
43
44 Argument *provideInitialHead() const { return createSentinel(); }
45 Argument *ensureHead(Argument*) const { return createSentinel(); }
46 static void noteHead(Argument*, Argument*) {}
47
48 private:
49 mutable ilist_half_node Sentinel;
50 };
36 template <>
37 struct SymbolTableListSentinelTraits
38 : public ilist_half_embedded_sentinel_traits {};
5139
5240 class Function : public GlobalObject, public ilist_node {
5341 public:
54 typedef iplist ArgumentListType;
55 typedef iplist BasicBlockListType;
42 typedef SymbolTableList ArgumentListType;
43 typedef SymbolTableList BasicBlockListType;
5644
5745 // BasicBlock iterators...
5846 typedef BasicBlockListType::iterator iterator;
8977 (Value ? Mask : 0u));
9078 }
9179
92 friend class SymbolTableListTraits, Module>;
80 friend class SymbolTableListTraits>;
9381
9482 void setParent(Module *parent);
9583
2222 namespace llvm {
2323
2424 class Module;
25 template
26 class SymbolTableListTraits;
25 template class SymbolTableListTraits;
2726
2827 class GlobalAlias : public GlobalValue, public ilist_node {
29 friend class SymbolTableListTraits, Module>;
28 friend class SymbolTableListTraits>;
3029 void operator=(const GlobalAlias &) = delete;
3130 GlobalAlias(const GlobalAlias &) = delete;
3231
2828
2929 class Module;
3030 class Constant;
31 template
32 class SymbolTableListTraits;
31 template class SymbolTableListTraits;
3332
3433 class GlobalVariable : public GlobalObject, public ilist_node {
35 friend class SymbolTableListTraits, Module>;
34 friend class SymbolTableListTraits>;
3635 void *operator new(size_t, unsigned) = delete;
3736 void operator=(const GlobalVariable &) = delete;
3837 GlobalVariable(const GlobalVariable &) = delete;
114114 }
115115 };
116116
117
118 typedef InstIterator,
119 Function::iterator, BasicBlock::iterator,
120 Instruction> inst_iterator;
121 typedef InstIterator,
122 Function::const_iterator,
123 BasicBlock::const_iterator,
117 typedef InstIterator, Function::iterator,
118 BasicBlock::iterator, Instruction> inst_iterator;
119 typedef InstIterator,
120 Function::const_iterator, BasicBlock::const_iterator,
124121 const Instruction> const_inst_iterator;
125122 typedef iterator_range inst_range;
126123 typedef iterator_range const_inst_range;
2929 struct AAMDNodes;
3030
3131 template <>
32 struct ilist_traits
33 : public SymbolTableListTraits {
34
35 /// \brief Return a node that marks the end of a list.
36 ///
37 /// The sentinel is relative to this instance, so we use a non-static
38 /// method.
39 Instruction *createSentinel() const;
40 static void destroySentinel(Instruction *) {}
41
42 Instruction *provideInitialHead() const { return createSentinel(); }
43 Instruction *ensureHead(Instruction *) const { return createSentinel(); }
44 static void noteHead(Instruction *, Instruction *) {}
45
46 private:
47 mutable ilist_half_node Sentinel;
48 };
32 struct SymbolTableListSentinelTraits
33 : public ilist_half_embedded_sentinel_traits {};
4934
5035 class Instruction : public User, public ilist_node {
5136 void operator=(const Instruction &) = delete;
8873 /// block and deletes it.
8974 ///
9075 /// \returns an iterator pointing to the element after the erased one
91 iplist::iterator eraseFromParent();
76 SymbolTableList::iterator eraseFromParent();
9277
9378 /// Insert an unlinked instruction into a basic block immediately before
9479 /// the specified instruction.
505490 (V ? HasMetadataBit : 0));
506491 }
507492
508 friend class SymbolTableListTraits, BasicBlock>;
493 friend class SymbolTableListTraits>;
509494 void setParent(BasicBlock *P);
510495 protected:
511496 // Instruction subclasses can stick up to 15 bits of stuff into the
530515 /// Create a copy of this instruction.
531516 Instruction *cloneImpl() const;
532517 };
533
534 inline Instruction *ilist_traits::createSentinel() const {
535 // Since i(p)lists always publicly derive from their corresponding traits,
536 // placing a data member in this class will augment the i(p)list. But since
537 // the NodeTy is expected to be publicly derive from ilist_node,
538 // there is a legal viable downcast from it to NodeTy. We use this trick to
539 // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the
540 // sentinel. Dereferencing the sentinel is forbidden (save the
541 // ilist_node), so no one will ever notice the superposition.
542 return static_cast(&Sentinel);
543 }
544518
545519 // Instruction* is only 4-byte aligned.
546520 template<>
3030 class LLVMContext;
3131 class Module;
3232 class ModuleSlotTracker;
33
34 template
35 class SymbolTableListTraits;
3633
3734 enum LLVMConstants : uint32_t {
3835 DEBUG_METADATA_VERSION = 3 // Current debug info version number.
11281125 ///
11291126 /// TODO: Inherit from Metadata.
11301127 class NamedMDNode : public ilist_node {
1131 friend class SymbolTableListTraits;
11321128 friend struct ilist_traits;
11331129 friend class LLVMContextImpl;
11341130 friend class Module;
3333 class RandomNumberGenerator;
3434 class StructType;
3535
36 template<> struct ilist_traits
37 : public SymbolTableListTraits {
38
39 // createSentinel is used to get hold of the node that marks the end of the
40 // list... (same trick used here as in ilist_traits)
41 Function *createSentinel() const {
42 return static_cast(&Sentinel);
43 }
44 static void destroySentinel(Function*) {}
45
46 Function *provideInitialHead() const { return createSentinel(); }
47 Function *ensureHead(Function*) const { return createSentinel(); }
48 static void noteHead(Function*, Function*) {}
49
50 private:
51 mutable ilist_node Sentinel;
52 };
53
54 template<> struct ilist_traits
55 : public SymbolTableListTraits {
56 // createSentinel is used to create a node that marks the end of the list.
57 GlobalVariable *createSentinel() const {
58 return static_cast(&Sentinel);
59 }
60 static void destroySentinel(GlobalVariable*) {}
61
62 GlobalVariable *provideInitialHead() const { return createSentinel(); }
63 GlobalVariable *ensureHead(GlobalVariable *) const {
64 return createSentinel();
65 }
66 static void noteHead(GlobalVariable *, GlobalVariable *) {}
67
68 private:
69 mutable ilist_node Sentinel;
70 };
71
72 template<> struct ilist_traits
73 : public SymbolTableListTraits {
74 // createSentinel is used to create a node that marks the end of the list.
75 GlobalAlias *createSentinel() const {
76 return static_cast(&Sentinel);
77 }
78 static void destroySentinel(GlobalAlias*) {}
79
80 GlobalAlias *provideInitialHead() const { return createSentinel(); }
81 GlobalAlias *ensureHead(GlobalAlias *) const { return createSentinel(); }
82 static void noteHead(GlobalAlias *, GlobalAlias *) {}
83
84 private:
85 mutable ilist_node Sentinel;
86 };
87
8836 template<> struct ilist_traits
8937 : public ilist_default_traits {
9038 // createSentinel is used to get hold of a node that marks the end of
12068 /// @{
12169 public:
12270 /// The type for the list of global variables.
123 typedef iplist GlobalListType;
71 typedef SymbolTableList GlobalListType;
12472 /// The type for the list of functions.
125 typedef iplist FunctionListType;
73 typedef SymbolTableList FunctionListType;
12674 /// The type for the list of aliases.
127 typedef iplist AliasListType;
75 typedef SymbolTableList AliasListType;
12876 /// The type for the list of named metadata.
12977 typedef ilist NamedMDListType;
13078 /// The type of the comdat "symbol" table.
3333 template class iplist;
3434 template struct ilist_traits;
3535
36 template
37 struct SymbolTableListSentinelTraits
38 : public ilist_embedded_sentinel_traits {};
39
40 /// Template metafunction to get the parent type for a symbol table list.
41 ///
42 /// Implementations create a typedef called \c type so that we only need a
43 /// single template parameter for the list and traits.
44 template struct SymbolTableListParentType {};
45 class Argument;
46 class BasicBlock;
47 class Function;
48 class Instruction;
49 class GlobalVariable;
50 class GlobalAlias;
51 class Module;
52 #define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT) \
53 template <> struct SymbolTableListParentType { typedef PARENT type; };
54 DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
55 DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function)
56 DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function)
57 DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
58 DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
59 DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
60 #undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
61
62 template class SymbolTableList;
63
3664 // ValueSubClass - The type of objects that I hold, e.g. Instruction.
3765 // ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
3866 //
39 template
40 class SymbolTableListTraits : public ilist_default_traits {
67 template
68 class SymbolTableListTraits
69 : public ilist_nextprev_traits,
70 public SymbolTableListSentinelTraits,
71 public ilist_node_traits {
72 typedef SymbolTableList ListTy;
73 typedef
74 typename SymbolTableListParentType::type ItemParentClass;
75
4176 public:
4277 SymbolTableListTraits() {}
4378
4782 ItemParentClass *getListOwner() {
4883 size_t Offset(size_t(&((ItemParentClass*)nullptr->*ItemParentClass::
4984 getSublistAccess(static_cast(nullptr)))));
50 iplist* Anchor(static_cast*>(this));
85 ListTy *Anchor(static_cast*>(this));
5186 return reinterpret_cast(reinterpret_cast(Anchor)-
5287 Offset);
5388 }
5489
55 static iplist &getList(ItemParentClass *Par) {
90 static ListTy &getList(ItemParentClass *Par) {
5691 return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr));
5792 }
5893
6398 public:
6499 void addNodeToList(ValueSubClass *V);
65100 void removeNodeFromList(ValueSubClass *V);
66 void transferNodesFromList(ilist_traits &L2,
101 void transferNodesFromList(SymbolTableListTraits &L2,
67102 ilist_iterator first,
68103 ilist_iterator last);
69104 //private:
73108 static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; }
74109 };
75110
111 /// List that automatically updates parent links and symbol tables.
112 ///
113 /// When nodes are inserted into and removed from this list, the associated
114 /// symbol table will be automatically updated. Similarly, parent links get
115 /// updated automatically.
116 template
117 class SymbolTableList : public iplist> {};
118
76119 } // End llvm namespace
77120
78121 #endif
1818 #include "llvm/Support/DataTypes.h"
1919
2020 namespace llvm {
21 template
22 class SymbolTableListTraits;
21 template class SymbolTableListTraits;
2322 class BasicBlock;
2423 class Function;
2524 class NamedMDNode;
3231 ///
3332 class ValueSymbolTable {
3433 friend class Value;
35 friend class SymbolTableListTraits;
36 friend class SymbolTableListTraits;
37 friend class SymbolTableListTraits;
38 friend class SymbolTableListTraits;
39 friend class SymbolTableListTraits;
40 friend class SymbolTableListTraits<GlobalAlias, Module>;
34 friend class SymbolTableListTraits<Argument>;
35 friend class SymbolTableListTraits;
36 friend class SymbolTableListTraits;
37 friend class SymbolTableListTraits;
38 friend class SymbolTableListTraits;
39 friend class SymbolTableListTraits;
4140 /// @name Types
4241 /// @{
4342 public:
3535
3636 // Explicit instantiation of SymbolTableListTraits since some of the methods
3737 // are not in the public header file...
38 template class llvm::SymbolTableListTraits, BasicBlock>;
38 template class llvm::SymbolTableListTraits>;
3939
4040 BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
4141 BasicBlock *InsertBefore)
3434
3535 // Explicit instantiations of SymbolTableListTraits since some of the methods
3636 // are not in the public header file...
37 template class llvm::SymbolTableListTraits;
38 template class llvm::SymbolTableListTraits<BasicBlock, Function>;
37 template class llvm::SymbolTableListTraits<Argument>;
38 template class llvm::SymbolTableListTraits;
3939
4040 //===----------------------------------------------------------------------===//
4141 // Argument Implementation
3737
3838 // Explicit instantiations of SymbolTableListTraits since some of the methods
3939 // are not in the public header file.
40 template class llvm::SymbolTableListTraits;
41 template class llvm::SymbolTableListTraits;
42 template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
40 template class llvm::SymbolTableListTraits<Function>;
41 template class llvm::SymbolTableListTraits;
42 template class llvm::SymbolTableListTraits;
4343
4444 //===----------------------------------------------------------------------===//
4545 // Primitive Module methods.
2323 /// setSymTabObject - This is called when (f.e.) the parent of a basic block
2424 /// changes. This requires us to remove all the instruction symtab entries from
2525 /// the current function and reinsert them into the new function.
26 template
27 template
28 void SymbolTableListTraits
29 ::setSymTabObject(TPtr *Dest, TPtr Src) {
26 template
27 template
28 void SymbolTableListTraits::setSymTabObject(TPtr *Dest,
29 TPtr Src) {
3030 // Get the old symtab and value list before doing the assignment.
3131 ValueSymbolTable *OldST = getSymTab(getListOwner());
3232
4040 if (OldST == NewST) return;
4141
4242 // Move all the elements from the old symtab to the new one.
43 iplist &ItemList = getList(getListOwner());
43 ListTy &ItemList = getList(getListOwner());
4444 if (ItemList.empty()) return;
4545
4646 if (OldST) {
5959
6060 }
6161
62 template
63 void SymbolTableListTraits
64 ::addNodeToList(ValueSubClass *V) {
62 template
63 void SymbolTableListTraits::addNodeToList(ValueSubClass *V) {
6564 assert(!V->getParent() && "Value already in a container!!");
6665 ItemParentClass *Owner = getListOwner();
6766 V->setParent(Owner);
7069 ST->reinsertValue(V);
7170 }
7271
73 template
74 void SymbolTableListTraits
75 ::removeNodeFromList(ValueSubClass *V) {
72 template
73 void SymbolTableListTraits::removeNodeFromList(
74 ValueSubClass *V) {
7675 V->setParent(nullptr);
7776 if (V->hasName())
7877 if (ValueSymbolTable *ST = getSymTab(getListOwner()))
7978 ST->removeValueName(V->getValueName());
8079 }
8180
82 template
83 void SymbolTableListTraits
84 ::transferNodesFromList(ilist_traits &L2,
85 ilist_iterator first,
86 ilist_iterator last) {
81 template
82 void SymbolTableListTraits::transferNodesFromList(
83 SymbolTableListTraits &L2, ilist_iterator first,
84 ilist_iterator last) {
8785 // We only have to do work here if transferring instructions between BBs
8886 ItemParentClass *NewIP = getListOwner(), *OldIP = L2.getListOwner();
8987 if (NewIP == OldIP) return; // No work to do at all...