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