BasicGOTAndStubsBuilder.h revision 360784
1//===--- BasicGOTAndStubsBuilder.h - Generic GOT/Stub creation --*- 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// A base for simple GOT and stub creation. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 14#define LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 15 16#include "llvm/ExecutionEngine/JITLink/JITLink.h" 17 18namespace llvm { 19namespace jitlink { 20 21template <typename BuilderImpl> class BasicGOTAndStubsBuilder { 22public: 23 BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {} 24 25 void run() { 26 // We're going to be adding new blocks, but we don't want to iterate over 27 // the newly added ones, so just copy the existing blocks out. 28 std::vector<Block *> Blocks(G.blocks().begin(), G.blocks().end()); 29 30 for (auto *B : Blocks) 31 for (auto &E : B->edges()) 32 if (impl().isGOTEdge(E)) 33 impl().fixGOTEdge(E, getGOTEntrySymbol(E.getTarget())); 34 else if (impl().isExternalBranchEdge(E)) 35 impl().fixExternalBranchEdge(E, getStubSymbol(E.getTarget())); 36 } 37 38protected: 39 Symbol &getGOTEntrySymbol(Symbol &Target) { 40 assert(Target.hasName() && "GOT edge cannot point to anonymous target"); 41 42 auto GOTEntryI = GOTEntries.find(Target.getName()); 43 44 // Build the entry if it doesn't exist. 45 if (GOTEntryI == GOTEntries.end()) { 46 auto &GOTEntry = impl().createGOTEntry(Target); 47 GOTEntryI = 48 GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first; 49 } 50 51 assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol"); 52 return *GOTEntryI->second; 53 } 54 55 Symbol &getStubSymbol(Symbol &Target) { 56 assert(Target.hasName() && 57 "External branch edge can not point to an anonymous target"); 58 auto StubI = Stubs.find(Target.getName()); 59 60 if (StubI == Stubs.end()) { 61 auto &StubSymbol = impl().createStub(Target); 62 StubI = Stubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first; 63 } 64 65 assert(StubI != Stubs.end() && "Count not get stub symbol"); 66 return *StubI->second; 67 } 68 69 LinkGraph &G; 70 71private: 72 BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); } 73 74 DenseMap<StringRef, Symbol *> GOTEntries; 75 DenseMap<StringRef, Symbol *> Stubs; 76}; 77 78} // end namespace jitlink 79} // end namespace llvm 80 81#endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H 82