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