10b57cec5SDimitry Andric //===- llvm/SymbolTableListTraits.h - Traits for iplist ---------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines a generic class that is used to implement the automatic
100b57cec5SDimitry Andric // symbol table manipulation that occurs when you put (for example) a named
110b57cec5SDimitry Andric // instruction into a basic block.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // The way that this is implemented is by using a special traits class with the
140b57cec5SDimitry Andric // intrusive list that makes up the list of instructions in a basic block.  When
150b57cec5SDimitry Andric // a new element is added to the list of instructions, the traits class is
160b57cec5SDimitry Andric // notified, allowing the symbol table to be updated.
170b57cec5SDimitry Andric //
180b57cec5SDimitry Andric // This generic class implements the traits class.  It must be generic so that
190b57cec5SDimitry Andric // it can work for all uses it, which include lists of instructions, basic
200b57cec5SDimitry Andric // blocks, arguments, functions, global variables, etc...
210b57cec5SDimitry Andric //
220b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #ifndef LLVM_IR_SYMBOLTABLELISTTRAITS_H
250b57cec5SDimitry Andric #define LLVM_IR_SYMBOLTABLELISTTRAITS_H
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #include "llvm/ADT/ilist.h"
280b57cec5SDimitry Andric #include "llvm/ADT/simple_ilist.h"
290b57cec5SDimitry Andric #include <cstddef>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace llvm {
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric class Argument;
340b57cec5SDimitry Andric class BasicBlock;
350b57cec5SDimitry Andric class Function;
360b57cec5SDimitry Andric class GlobalAlias;
370b57cec5SDimitry Andric class GlobalIFunc;
380b57cec5SDimitry Andric class GlobalVariable;
390b57cec5SDimitry Andric class Instruction;
400b57cec5SDimitry Andric class Module;
410b57cec5SDimitry Andric class ValueSymbolTable;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// Template metafunction to get the parent type for a symbol table list.
440b57cec5SDimitry Andric ///
450b57cec5SDimitry Andric /// Implementations create a typedef called \c type so that we only need a
460b57cec5SDimitry Andric /// single template parameter for the list and traits.
470b57cec5SDimitry Andric template <typename NodeTy> struct SymbolTableListParentType {};
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric #define DEFINE_SYMBOL_TABLE_PARENT_TYPE(NODE, PARENT)                          \
500b57cec5SDimitry Andric   template <> struct SymbolTableListParentType<NODE> { using type = PARENT; };
510b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(Instruction, BasicBlock)
520b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(BasicBlock, Function)
530b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(Argument, Function)
540b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(Function, Module)
550b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable, Module)
560b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalAlias, Module)
570b57cec5SDimitry Andric DEFINE_SYMBOL_TABLE_PARENT_TYPE(GlobalIFunc, Module)
580b57cec5SDimitry Andric #undef DEFINE_SYMBOL_TABLE_PARENT_TYPE
590b57cec5SDimitry Andric 
605f757f3fSDimitry Andric template <typename NodeTy, typename... Args> class SymbolTableList;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric // ValueSubClass   - The type of objects that I hold, e.g. Instruction.
630b57cec5SDimitry Andric // ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
645f757f3fSDimitry Andric // OptionsT        - Extra options to ilist nodes.
650b57cec5SDimitry Andric //
665f757f3fSDimitry Andric template <typename ValueSubClass, typename... Args>
670b57cec5SDimitry Andric class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
685f757f3fSDimitry Andric   using ListTy = SymbolTableList<ValueSubClass, Args...>;
695f757f3fSDimitry Andric   using iterator = typename simple_ilist<ValueSubClass, Args...>::iterator;
700b57cec5SDimitry Andric   using ItemParentClass =
710b57cec5SDimitry Andric       typename SymbolTableListParentType<ValueSubClass>::type;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric public:
740b57cec5SDimitry Andric   SymbolTableListTraits() = default;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric private:
770b57cec5SDimitry Andric   /// getListOwner - Return the object that owns this list.  If this is a list
780b57cec5SDimitry Andric   /// of instructions, it returns the BasicBlock that owns them.
getListOwner()790b57cec5SDimitry Andric   ItemParentClass *getListOwner() {
80e8d8bef9SDimitry Andric     size_t Offset = reinterpret_cast<size_t>(
81e8d8bef9SDimitry Andric         &((ItemParentClass *)nullptr->*ItemParentClass::getSublistAccess(
82e8d8bef9SDimitry Andric                                            static_cast<ValueSubClass *>(
83e8d8bef9SDimitry Andric                                                nullptr))));
84e8d8bef9SDimitry Andric     ListTy *Anchor = static_cast<ListTy *>(this);
850b57cec5SDimitry Andric     return reinterpret_cast<ItemParentClass*>(reinterpret_cast<char*>(Anchor)-
860b57cec5SDimitry Andric                                               Offset);
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric 
getList(ItemParentClass * Par)890b57cec5SDimitry Andric   static ListTy &getList(ItemParentClass *Par) {
900b57cec5SDimitry Andric     return Par->*(Par->getSublistAccess((ValueSubClass*)nullptr));
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
getSymTab(ItemParentClass * Par)930b57cec5SDimitry Andric   static ValueSymbolTable *getSymTab(ItemParentClass *Par) {
940b57cec5SDimitry Andric     return Par ? toPtr(Par->getValueSymbolTable()) : nullptr;
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric public:
980b57cec5SDimitry Andric   void addNodeToList(ValueSubClass *V);
990b57cec5SDimitry Andric   void removeNodeFromList(ValueSubClass *V);
1000b57cec5SDimitry Andric   void transferNodesFromList(SymbolTableListTraits &L2, iterator first,
1010b57cec5SDimitry Andric                              iterator last);
1020b57cec5SDimitry Andric   // private:
1030b57cec5SDimitry Andric   template<typename TPtr>
1040b57cec5SDimitry Andric   void setSymTabObject(TPtr *, TPtr);
toPtr(ValueSymbolTable * P)1050b57cec5SDimitry Andric   static ValueSymbolTable *toPtr(ValueSymbolTable *P) { return P; }
toPtr(ValueSymbolTable & R)1060b57cec5SDimitry Andric   static ValueSymbolTable *toPtr(ValueSymbolTable &R) { return &R; }
1070b57cec5SDimitry Andric };
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric /// List that automatically updates parent links and symbol tables.
1100b57cec5SDimitry Andric ///
1110b57cec5SDimitry Andric /// When nodes are inserted into and removed from this list, the associated
1120b57cec5SDimitry Andric /// symbol table will be automatically updated.  Similarly, parent links get
1130b57cec5SDimitry Andric /// updated automatically.
1145f757f3fSDimitry Andric template <class T, typename... Args>
1155f757f3fSDimitry Andric class SymbolTableList : public iplist_impl<simple_ilist<T, Args...>,
1165f757f3fSDimitry Andric                                            SymbolTableListTraits<T, Args...>> {
1175f757f3fSDimitry Andric };
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric } // end namespace llvm
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric #endif // LLVM_IR_SYMBOLTABLELISTTRAITS_H
122