[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / ExecutionEngine / JITLink / MachOLinkGraphBuilder.h
blobe1123cd1104876f573ea3b16f0906ff7c2f09741
1 //===----- MachOLinkGraphBuilder.h - MachO LinkGraph builder ----*- 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 // Generic MachO LinkGraph building code.
11 //===----------------------------------------------------------------------===//
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H
16 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
18 #include "EHFrameSupportImpl.h"
19 #include "JITLinkGeneric.h"
20 #include "llvm/Object/MachO.h"
22 #include <list>
24 namespace llvm {
25 namespace jitlink {
27 class MachOLinkGraphBuilder {
28 public:
29 virtual ~MachOLinkGraphBuilder();
30 Expected<std::unique_ptr<LinkGraph>> buildGraph();
32 protected:
33 class MachOEHFrameBinaryParser : public EHFrameBinaryParser {
34 public:
35 MachOEHFrameBinaryParser(MachOLinkGraphBuilder &Builder,
36 JITTargetAddress EHFrameAddress,
37 StringRef EHFrameContent, Section &EHFrameSection,
38 uint64_t CIEAlignment, uint64_t FDEAlignment,
39 Edge::Kind FDEToCIERelocKind,
40 Edge::Kind FDEToTargetRelocKind)
41 : EHFrameBinaryParser(EHFrameAddress, EHFrameContent,
42 Builder.getGraph().getPointerSize(),
43 Builder.getGraph().getEndianness()),
44 Builder(Builder), EHFrameSection(EHFrameSection),
45 CIEAlignment(CIEAlignment), FDEAlignment(FDEAlignment),
46 FDEToCIERelocKind(FDEToCIERelocKind),
47 FDEToTargetRelocKind(FDEToTargetRelocKind) {}
49 Symbol *getSymbolAtAddress(JITTargetAddress Address) override {
50 if (auto *Sym = Builder.getSymbolByAddress(Address))
51 if (Sym->getAddress() == Address)
52 return Sym;
53 return nullptr;
56 Symbol &createCIERecord(JITTargetAddress RecordAddr,
57 StringRef RecordContent) override {
58 auto &G = Builder.getGraph();
59 auto &B = G.createContentBlock(EHFrameSection, RecordContent, RecordAddr,
60 CIEAlignment, 0);
61 auto &CIESymbol =
62 G.addAnonymousSymbol(B, 0, RecordContent.size(), false, false);
63 Builder.setCanonicalSymbol(CIESymbol);
64 return CIESymbol;
67 Expected<Symbol &> createFDERecord(JITTargetAddress RecordAddr,
68 StringRef RecordContent, Symbol &CIE,
69 size_t CIEOffset, Symbol &Func,
70 size_t FuncOffset, Symbol *LSDA,
71 size_t LSDAOffset) override {
72 auto &G = Builder.getGraph();
73 auto &B = G.createContentBlock(EHFrameSection, RecordContent, RecordAddr,
74 FDEAlignment, 0);
76 // Add edges to CIE, Func, and (conditionally) LSDA.
77 B.addEdge(FDEToCIERelocKind, CIEOffset, CIE, 0);
78 B.addEdge(FDEToTargetRelocKind, FuncOffset, Func, 0);
80 if (LSDA)
81 B.addEdge(FDEToTargetRelocKind, LSDAOffset, *LSDA, 0);
83 auto &FDESymbol =
84 G.addAnonymousSymbol(B, 0, RecordContent.size(), false, false);
86 // Add a keep-alive relocation from the function to the FDE to ensure it
87 // is not dead stripped.
88 Func.getBlock().addEdge(Edge::KeepAlive, 0, FDESymbol, 0);
90 return FDESymbol;
93 private:
94 MachOLinkGraphBuilder &Builder;
95 Section &EHFrameSection;
96 uint64_t CIEAlignment;
97 uint64_t FDEAlignment;
98 Edge::Kind FDEToCIERelocKind;
99 Edge::Kind FDEToTargetRelocKind;
102 struct NormalizedSymbol {
103 friend class MachOLinkGraphBuilder;
105 private:
106 NormalizedSymbol(Optional<StringRef> Name, uint64_t Value, uint8_t Type,
107 uint8_t Sect, uint16_t Desc, Linkage L, Scope S)
108 : Name(Name), Value(Value), Type(Type), Sect(Sect), Desc(Desc), L(L),
109 S(S) {
110 assert((!Name || !Name->empty()) && "Name must be none or non-empty");
113 public:
114 NormalizedSymbol(const NormalizedSymbol &) = delete;
115 NormalizedSymbol &operator=(const NormalizedSymbol &) = delete;
116 NormalizedSymbol(NormalizedSymbol &&) = delete;
117 NormalizedSymbol &operator=(NormalizedSymbol &&) = delete;
119 Optional<StringRef> Name;
120 uint64_t Value = 0;
121 uint8_t Type = 0;
122 uint8_t Sect = 0;
123 uint16_t Desc = 0;
124 Linkage L = Linkage::Strong;
125 Scope S = Scope::Default;
126 Symbol *GraphSymbol = nullptr;
129 class NormalizedSection {
130 friend class MachOLinkGraphBuilder;
132 private:
133 NormalizedSection() = default;
135 public:
136 Section *GraphSection = nullptr;
137 uint64_t Address = 0;
138 uint64_t Size = 0;
139 uint64_t Alignment = 0;
140 uint32_t Flags = 0;
141 const char *Data = nullptr;
144 using SectionParserFunction = std::function<Error(NormalizedSection &S)>;
146 MachOLinkGraphBuilder(const object::MachOObjectFile &Obj);
148 LinkGraph &getGraph() const { return *G; }
150 const object::MachOObjectFile &getObject() const { return Obj; }
152 void addCustomSectionParser(StringRef SectionName,
153 SectionParserFunction Parse);
155 virtual Error addRelocations() = 0;
157 /// Create a symbol.
158 template <typename... ArgTs>
159 NormalizedSymbol &createNormalizedSymbol(ArgTs &&... Args) {
160 NormalizedSymbol *Sym = reinterpret_cast<NormalizedSymbol *>(
161 Allocator.Allocate<NormalizedSymbol>());
162 new (Sym) NormalizedSymbol(std::forward<ArgTs>(Args)...);
163 return *Sym;
166 /// Index is zero-based (MachO section indexes are usually one-based) and
167 /// assumed to be in-range. Client is responsible for checking.
168 NormalizedSection &getSectionByIndex(unsigned Index) {
169 auto I = IndexToSection.find(Index);
170 assert(I != IndexToSection.end() && "No section recorded at index");
171 return I->second;
174 /// Try to get the section at the given index. Will return an error if the
175 /// given index is out of range, or if no section has been added for the given
176 /// index.
177 Expected<NormalizedSection &> findSectionByIndex(unsigned Index) {
178 auto I = IndexToSection.find(Index);
179 if (I == IndexToSection.end())
180 return make_error<JITLinkError>("No section recorded for index " +
181 formatv("{0:u}", Index));
182 return I->second;
185 /// Try to get the symbol at the given index. Will return an error if the
186 /// given index is out of range, or if no symbol has been added for the given
187 /// index.
188 Expected<NormalizedSymbol &> findSymbolByIndex(uint64_t Index) {
189 if (Index >= IndexToSymbol.size())
190 return make_error<JITLinkError>("Symbol index out of range");
191 auto *Sym = IndexToSymbol[Index];
192 if (!Sym)
193 return make_error<JITLinkError>("No symbol at index " +
194 formatv("{0:u}", Index));
195 return *Sym;
198 /// Returns the symbol with the highest address not greater than the search
199 /// address, or null if no such symbol exists.
200 Symbol *getSymbolByAddress(JITTargetAddress Address) {
201 auto I = AddrToCanonicalSymbol.upper_bound(Address);
202 if (I == AddrToCanonicalSymbol.begin())
203 return nullptr;
204 return std::prev(I)->second;
207 /// Returns the symbol with the highest address not greater than the search
208 /// address, or an error if no such symbol exists.
209 Expected<Symbol &> findSymbolByAddress(JITTargetAddress Address) {
210 auto *Sym = getSymbolByAddress(Address);
211 if (Sym)
212 if (Address < Sym->getAddress() + Sym->getSize())
213 return *Sym;
214 return make_error<JITLinkError>("No symbol covering address " +
215 formatv("{0:x16}", Address));
218 static Linkage getLinkage(uint16_t Desc);
219 static Scope getScope(StringRef Name, uint8_t Type);
220 static bool isAltEntry(const NormalizedSymbol &NSym);
222 private:
223 static unsigned getPointerSize(const object::MachOObjectFile &Obj);
224 static support::endianness getEndianness(const object::MachOObjectFile &Obj);
226 void setCanonicalSymbol(Symbol &Sym) {
227 auto *&CanonicalSymEntry = AddrToCanonicalSymbol[Sym.getAddress()];
228 // There should be no symbol at this address, or, if there is,
229 // it should be a zero-sized symbol from an empty section (which
230 // we can safely override).
231 assert((!CanonicalSymEntry || CanonicalSymEntry->getSize() == 0) &&
232 "Duplicate canonical symbol at address");
233 CanonicalSymEntry = &Sym;
236 Section &getCommonSection();
237 void addSectionStartSymAndBlock(Section &GraphSec, uint64_t Address,
238 const char *Data, uint64_t Size,
239 uint32_t Alignment, bool IsLive);
241 Error createNormalizedSections();
242 Error createNormalizedSymbols();
244 /// Create graph blocks and symbols for externals, absolutes, commons and
245 /// all defined symbols in sections without custom parsers.
246 Error graphifyRegularSymbols();
248 /// Create graph blocks and symbols for all sections.
249 Error graphifySectionsWithCustomParsers();
251 // Put the BumpPtrAllocator first so that we don't free any of the underlying
252 // memory until the Symbol/Addressable destructors have been run.
253 BumpPtrAllocator Allocator;
255 const object::MachOObjectFile &Obj;
256 std::unique_ptr<LinkGraph> G;
258 DenseMap<unsigned, NormalizedSection> IndexToSection;
259 Section *CommonSection = nullptr;
261 DenseMap<uint32_t, NormalizedSymbol *> IndexToSymbol;
262 std::map<JITTargetAddress, Symbol *> AddrToCanonicalSymbol;
263 StringMap<SectionParserFunction> CustomSectionParserFunctions;
266 } // end namespace jitlink
267 } // end namespace llvm
269 #endif // LIB_EXECUTIONENGINE_JITLINK_MACHOLINKGRAPHBUILDER_H