blob: b47a798c7603bb88899870460b73558970a6d721 [file] [log] [blame]
Lang Hames01915312019-04-21 03:14:42 +00001//===--- 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:
Lang Hames4e920e52019-10-04 03:55:26 +000023 BasicGOTAndStubsBuilder(LinkGraph &G) : G(G) {}
Lang Hames01915312019-04-21 03:14:42 +000024
25 void run() {
Lang Hames4e920e52019-10-04 03:55:26 +000026 // 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());
Lang Hames01915312019-04-21 03:14:42 +000029
Lang Hames4e920e52019-10-04 03:55:26 +000030 for (auto *B : Blocks)
31 for (auto &E : B->edges())
Lang Hames01915312019-04-21 03:14:42 +000032 if (impl().isGOTEdge(E))
Lang Hames4e920e52019-10-04 03:55:26 +000033 impl().fixGOTEdge(E, getGOTEntrySymbol(E.getTarget()));
Lang Hames01915312019-04-21 03:14:42 +000034 else if (impl().isExternalBranchEdge(E))
Lang Hames4e920e52019-10-04 03:55:26 +000035 impl().fixExternalBranchEdge(E, getStubSymbol(E.getTarget()));
Lang Hames01915312019-04-21 03:14:42 +000036 }
37
38protected:
Lang Hames4e920e52019-10-04 03:55:26 +000039 Symbol &getGOTEntrySymbol(Symbol &Target) {
Lang Hames01915312019-04-21 03:14:42 +000040 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
Lang Hames4e920e52019-10-04 03:55:26 +000051 assert(GOTEntryI != GOTEntries.end() && "Could not get GOT entry symbol");
Lang Hames01915312019-04-21 03:14:42 +000052 return *GOTEntryI->second;
53 }
54
Lang Hames4e920e52019-10-04 03:55:26 +000055 Symbol &getStubSymbol(Symbol &Target) {
Lang Hames01915312019-04-21 03:14:42 +000056 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()) {
Lang Hames4e920e52019-10-04 03:55:26 +000061 auto &StubSymbol = impl().createStub(Target);
62 StubI = Stubs.insert(std::make_pair(Target.getName(), &StubSymbol)).first;
Lang Hames01915312019-04-21 03:14:42 +000063 }
64
Lang Hames4e920e52019-10-04 03:55:26 +000065 assert(StubI != Stubs.end() && "Count not get stub symbol");
Lang Hames01915312019-04-21 03:14:42 +000066 return *StubI->second;
67 }
68
Lang Hames4e920e52019-10-04 03:55:26 +000069 LinkGraph &G;
Lang Hames01915312019-04-21 03:14:42 +000070
71private:
72 BuilderImpl &impl() { return static_cast<BuilderImpl &>(*this); }
73
Lang Hames4e920e52019-10-04 03:55:26 +000074 DenseMap<StringRef, Symbol *> GOTEntries;
75 DenseMap<StringRef, Symbol *> Stubs;
Lang Hames01915312019-04-21 03:14:42 +000076};
77
78} // end namespace jitlink
79} // end namespace llvm
80
81#endif // LLVM_LIB_EXECUTIONENGINE_JITLINK_BASICGOTANDSTUBSBUILDER_H