| //===--------- DefineExternalSectionStartAndEndSymbols.h --------*- C++ -*-===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Utility class for recognizing external section start and end symbols and | |
| // transforming them into defined symbols for the start and end blocks of the | |
| // associated Section. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H | |
| #define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H | |
| #include "llvm/ExecutionEngine/JITLink/JITLink.h" | |
| #include "llvm/Support/Debug.h" | |
| #define DEBUG_TYPE "jitlink" | |
| namespace llvm { | |
| namespace jitlink { | |
| struct SectionRangeSymbolDesc { | |
| SectionRangeSymbolDesc() = default; | |
| SectionRangeSymbolDesc(Section &Sec, bool IsStart) | |
| : Sec(&Sec), IsStart(IsStart) {} | |
| Section *Sec = nullptr; | |
| bool IsStart = false; | |
| }; | |
| /// Pass implementation for the createDefineExternalSectionStartAndEndSymbols | |
| /// function. | |
| template <typename SymbolIdentifierFunction> | |
| class DefineExternalSectionStartAndEndSymbols { | |
| public: | |
| DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F) | |
| : F(std::move(F)) {} | |
| Error operator()(LinkGraph &G) { | |
| // This pass will affect the external symbols set, so copy them out into a | |
| // vector and iterate over that. | |
| std::vector<Symbol *> Externals(G.external_symbols().begin(), | |
| G.external_symbols().end()); | |
| for (auto *Sym : Externals) { | |
| SectionRangeSymbolDesc D = F(G, *Sym); | |
| if (D.Sec) { | |
| auto &SR = getSectionRange(*D.Sec); | |
| if (D.IsStart) { | |
| if (SR.empty()) | |
| G.makeAbsolute(*Sym, orc::ExecutorAddr()); | |
| else | |
| G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong, | |
| Scope::Local, false); | |
| } else { | |
| if (SR.empty()) | |
| G.makeAbsolute(*Sym, orc::ExecutorAddr()); | |
| else | |
| G.makeDefined(*Sym, *SR.getLastBlock(), | |
| SR.getLastBlock()->getSize(), 0, Linkage::Strong, | |
| Scope::Local, false); | |
| } | |
| } | |
| } | |
| return Error::success(); | |
| } | |
| private: | |
| SectionRange &getSectionRange(Section &Sec) { | |
| auto I = SectionRanges.find(&Sec); | |
| if (I == SectionRanges.end()) | |
| I = SectionRanges.insert(std::make_pair(&Sec, SectionRange(Sec))).first; | |
| return I->second; | |
| } | |
| DenseMap<Section *, SectionRange> SectionRanges; | |
| SymbolIdentifierFunction F; | |
| }; | |
| /// Returns a JITLink pass (as a function class) that uses the given symbol | |
| /// identification function to identify external section start and end symbols | |
| /// (and their associated Section*s) and transform the identified externals | |
| /// into defined symbols pointing to the start of the first block in the | |
| /// section and the end of the last (start and end symbols for empty sections | |
| /// will be transformed into absolute symbols at address 0). | |
| /// | |
| /// The identification function should be callable as | |
| /// | |
| /// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym) | |
| /// | |
| /// If Sym is not a section range start or end symbol then a default | |
| /// constructed SectionRangeSymbolDesc should be returned. If Sym is a start | |
| /// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to | |
| /// the target Section. If Sym is an end symbol then | |
| /// SectionRangeSymbolDesc(Sec, false) should be returned. | |
| /// | |
| /// This pass should be run in the PostAllocationPass pipeline, at which point | |
| /// all blocks should have been assigned their final addresses. | |
| template <typename SymbolIdentifierFunction> | |
| DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction> | |
| createDefineExternalSectionStartAndEndSymbolsPass( | |
| SymbolIdentifierFunction &&F) { | |
| return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>( | |
| std::forward<SymbolIdentifierFunction>(F)); | |
| } | |
| } // end namespace jitlink | |
| } // end namespace llvm | |
| #undef DEBUG_TYPE | |
| #endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H |