[AMDGPU] Test codegen'ing True16 additions.
[llvm-project.git] / llvm / lib / ExecutionEngine / JITLink / COFFLinkGraphBuilder.h
blobe64823759540a7656b537645f1449749767c79c7
1 //===----- COFFLinkGraphBuilder.h - COFF 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 COFF LinkGraph building code.
11 //===----------------------------------------------------------------------===//
13 #ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
14 #define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
19 #include "llvm/Object/COFF.h"
21 #include "COFFDirectiveParser.h"
22 #include "EHFrameSupportImpl.h"
23 #include "JITLinkGeneric.h"
25 #define DEBUG_TYPE "jitlink"
27 #include <list>
29 namespace llvm {
30 namespace jitlink {
32 class COFFLinkGraphBuilder {
33 public:
34 virtual ~COFFLinkGraphBuilder();
35 Expected<std::unique_ptr<LinkGraph>> buildGraph();
37 protected:
38 using COFFSectionIndex = int32_t;
39 using COFFSymbolIndex = int32_t;
41 COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
42 SubtargetFeatures Features,
43 LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
45 LinkGraph &getGraph() const { return *G; }
47 const object::COFFObjectFile &getObject() const { return Obj; }
49 virtual Error addRelocations() = 0;
51 Error graphifySections();
52 Error graphifySymbols();
54 void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
55 Symbol &Sym) {
56 assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
57 GraphSymbols[SymIndex] = &Sym;
58 if (!COFF::isReservedSectionNumber(SecIndex))
59 SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
62 Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
63 if (SymIndex < 0 ||
64 SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
65 return nullptr;
66 return GraphSymbols[SymIndex];
69 void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
70 assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
71 assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
72 GraphBlocks[SecIndex] = B;
75 Block *getGraphBlock(COFFSectionIndex SecIndex) const {
76 if (SecIndex <= 0 ||
77 SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
78 return nullptr;
79 return GraphBlocks[SecIndex];
82 object::COFFObjectFile::section_iterator_range sections() const {
83 return Obj.sections();
86 /// Traverse all matching relocation records in the given section. The handler
87 /// function Func should be callable with this signature:
88 /// Error(const object::RelocationRef&,
89 /// const object::SectionRef&, Section &)
90 ///
91 template <typename RelocHandlerFunction>
92 Error forEachRelocation(const object::SectionRef &RelSec,
93 RelocHandlerFunction &&Func,
94 bool ProcessDebugSections = false);
96 /// Traverse all matching relocation records in the given section. Convenience
97 /// wrapper to allow passing a member function for the handler.
98 ///
99 template <typename ClassT, typename RelocHandlerMethod>
100 Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
101 RelocHandlerMethod &&Method,
102 bool ProcessDebugSections = false) {
103 return forEachRelocation(
104 RelSec,
105 [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
106 return (Instance->*Method)(Rel, Target, GS);
108 ProcessDebugSections);
111 private:
112 // Pending comdat symbol export that is initiated by the first symbol of
113 // COMDAT sequence.
114 struct ComdatExportRequest {
115 COFFSymbolIndex SymbolIndex;
116 jitlink::Linkage Linkage;
117 orc::ExecutorAddrDiff Size;
119 std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;
121 // This represents a pending request to create a weak external symbol with a
122 // name.
123 struct WeakExternalRequest {
124 COFFSymbolIndex Alias;
125 COFFSymbolIndex Target;
126 uint32_t Characteristics;
127 StringRef SymbolName;
129 std::vector<WeakExternalRequest> WeakExternalRequests;
131 // Per COFF section jitlink symbol set sorted by offset.
132 // Used for calculating implicit size of defined symbols.
133 using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
134 std::vector<SymbolSet> SymbolSets;
136 Section &getCommonSection();
138 Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
139 object::COFFSymbolRef Symbol,
140 const object::coff_section *Section);
141 Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
142 Symbol &Target);
143 Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
144 StringRef SymbolName,
145 object::COFFSymbolRef Symbol,
146 const object::coff_section *Section);
147 Expected<Symbol *> createCOMDATExportRequest(
148 COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
149 const object::coff_aux_section_definition *Definition);
150 Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
151 StringRef SymbolName,
152 object::COFFSymbolRef Symbol);
154 Error handleDirectiveSection(StringRef Str);
155 Error flushWeakAliasRequests();
156 Error handleAlternateNames();
157 Error calculateImplicitSizeOfSymbols();
159 static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
160 const object::coff_section *Section);
161 static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
162 const object::coff_section *Section);
163 static bool isComdatSection(const object::coff_section *Section);
164 static unsigned getPointerSize(const object::COFFObjectFile &Obj);
165 static support::endianness getEndianness(const object::COFFObjectFile &Obj);
166 static StringRef getDLLImportStubPrefix() { return "__imp_"; }
167 static StringRef getDirectiveSectionName() { return ".drectve"; }
168 StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
169 const object::coff_section *Sec,
170 object::COFFSymbolRef Sym);
172 const object::COFFObjectFile &Obj;
173 std::unique_ptr<LinkGraph> G;
174 COFFDirectiveParser DirectiveParser;
176 Section *CommonSection = nullptr;
177 std::vector<Block *> GraphBlocks;
178 std::vector<Symbol *> GraphSymbols;
180 DenseMap<StringRef, StringRef> AlternateNames;
181 DenseMap<StringRef, Symbol *> ExternalSymbols;
182 DenseMap<StringRef, Symbol *> DefinedSymbols;
185 template <typename RelocHandlerFunction>
186 Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
187 RelocHandlerFunction &&Func,
188 bool ProcessDebugSections) {
190 auto COFFRelSect = Obj.getCOFFSection(RelSec);
192 // Target sections have names in valid COFF object files.
193 Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
194 if (!Name)
195 return Name.takeError();
197 // Skip the unhandled metadata sections.
198 if (*Name == ".voltbl")
199 return Error::success();
200 LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
202 // Lookup the link-graph node corresponding to the target section name.
203 auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
204 if (!BlockToFix)
205 return make_error<StringError>(
206 "Referencing a section that wasn't added to the graph: " + *Name,
207 inconvertibleErrorCode());
209 // Let the callee process relocation entries one by one.
210 for (const auto &R : RelSec.relocations())
211 if (Error Err = Func(R, RelSec, *BlockToFix))
212 return Err;
214 LLVM_DEBUG(dbgs() << "\n");
215 return Error::success();
218 } // end namespace jitlink
219 } // end namespace llvm
221 #endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H