1 //===---------------------- TableManager.h ----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Fix edge for edge that needs an entry to reference the target symbol 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_JITLINK_TABLEMANAGER_H 14 #define LLVM_EXECUTIONENGINE_JITLINK_TABLEMANAGER_H 15 16 #include "llvm/ExecutionEngine/JITLink/JITLink.h" 17 #include "llvm/Support/Debug.h" 18 19 namespace llvm { 20 namespace jitlink { 21 22 /// A CRTP base for tables that are built on demand, e.g. Global Offset Tables 23 /// and Procedure Linkage Tables. 24 /// The getEntyrForTarget function returns the table entry corresponding to the 25 /// given target, calling down to the implementation class to build an entry if 26 /// one does not already exist. 27 template <typename TableManagerImplT> class TableManager { 28 public: 29 /// Return the constructed entry 30 /// 31 /// Use parameter G to construct the entry for target symbol getEntryForTarget(LinkGraph & G,Symbol & Target)32 Symbol &getEntryForTarget(LinkGraph &G, Symbol &Target) { 33 assert(Target.hasName() && "Edge cannot point to anonymous target"); 34 35 auto EntryI = Entries.find(Target.getName()); 36 37 // Build the entry if it doesn't exist. 38 if (EntryI == Entries.end()) { 39 auto &Entry = impl().createEntry(G, Target); 40 DEBUG_WITH_TYPE("jitlink", { 41 dbgs() << " Created " << impl().getSectionName() << " entry for " 42 << Target.getName() << ": " << Entry << "\n"; 43 }); 44 EntryI = Entries.insert(std::make_pair(Target.getName(), &Entry)).first; 45 } 46 47 assert(EntryI != Entries.end() && "Could not get entry symbol"); 48 DEBUG_WITH_TYPE("jitlink", { 49 dbgs() << " Using " << impl().getSectionName() << " entry " 50 << *EntryI->second << "\n"; 51 }); 52 return *EntryI->second; 53 } 54 55 /// Register a pre-existing entry. 56 /// 57 /// Objects may include pre-existing table entries (e.g. for GOTs). 58 /// This method can be used to register those entries so that they will not 59 /// be duplicated by createEntry the first time that getEntryForTarget is 60 /// called. registerPreExistingEntry(Symbol & Target,Symbol & Entry)61 bool registerPreExistingEntry(Symbol &Target, Symbol &Entry) { 62 assert(Target.hasName() && "Edge cannot point to anonymous target"); 63 auto Res = Entries.insert({ 64 Target.getName(), 65 &Entry, 66 }); 67 return Res.second; 68 } 69 70 private: impl()71 TableManagerImplT &impl() { return static_cast<TableManagerImplT &>(*this); } 72 DenseMap<StringRef, Symbol *> Entries; 73 }; 74 75 } // namespace jitlink 76 } // namespace llvm 77 78 #endif 79