]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/BasicGOTAndStubsBuilder.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / ExecutionEngine / JITLink / BasicGOTAndStubsBuilder.h
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
18 namespace llvm {
19 namespace jitlink {
20
21 template <typename BuilderImpl> class BasicGOTAndStubsBuilder {
22 public:
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
38 protected:
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
71 private:
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