| //===--- BasicGOTAndStubsBuilder.h - Generic GOT/Stub creation --*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // A base for simple GOT and stub creation. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H | |
| #define LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H | |
| #include "llvm/ExecutionEngine/JITLink/JITLink.h" | |
| namespace llvm { | |
| namespace jitlink { | |
| template <typename BuilderImpl> class BasicGOTAndStubsBuilder { | |
| public: | |
| BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {} | |
| void run() { | |
| // We're going to be adding new blocks, but we don't want to iterate over | |
| // the newly added ones, so just copy the existing blocks out. | |
| std::vector<Block *> Blocks(G.blocks().begin(), G.blocks().end()); | |
| for (auto *B : Blocks) | |
| for (auto &E : B->edges()) | |
| if (impl().isGOTEdge(E)) | |
| impl().fixGOTEdge(E, getGOTEntrySymbol(E.getTarget())); | |
| else if (impl().isExternalBranchEdge(E)) | |
| impl().fixExternalBranchEdge(E, getStubSymbol(E.getTarget())); | |
| } | |
| protected: | |
| Symbol &getGOTEntrySymbol(Symbol &Target) { | |
| assert(Target.hasName() && "GOT edge cannot point to anonymous target"); | |
| auto GOTEntryI = GOTEntries.find(Target.getName()); | |
| // Build the entry if it doesn't exist. | |
| if (GOTEntryI == GOTEntries.end()) { | |
| auto &GOTEntry = impl().createGOTEntry(Target); | |
| GOTEntryI = | |
| GOTEntries.insert(std::make_pair(Target.getName(), &GOTEntry)).first; | |
| } | |
| assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol"); | |
| return *GOTEntryI->second; | |
| } | |
| Symbol &getStubSymbol(Symbol &Target) { | |
| assert(Target.hasName() && | |
| "External branch edge can not point to an anonymous target"); | |
| auto StubI = Stubs.find(Target.getName()); | |
| if (StubI == Stubs.end()) { | |
| auto &StubSymbol = impl().createStub(Target); | |
| StubI = Stubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first; | |
| } | |
| assert(StubI != Stubs.end() && "Count not get stub symbol"); | |
| return *StubI->second; | |
| } | |
| LinkGraph &G; | |
| private: | |
| BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); } | |
| DenseMap<StringRef, Symbol *> GOTEntries; | |
| DenseMap<StringRef, Symbol *> Stubs; | |
| }; | |
| } // end namespace jitlink | |
| } // end namespace llvm | |
| #endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H |