1fe6060f1SDimitry Andric //===--------- DefineExternalSectionStartAndEndSymbols.h --------*- C++ -*-===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // Utility class for recognizing external section start and end symbols and 10fe6060f1SDimitry Andric // transforming them into defined symbols for the start and end blocks of the 11fe6060f1SDimitry Andric // associated Section. 12fe6060f1SDimitry Andric // 13fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 14fe6060f1SDimitry Andric 15fe6060f1SDimitry Andric #ifndef LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 16fe6060f1SDimitry Andric #define LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 17fe6060f1SDimitry Andric 18fe6060f1SDimitry Andric #include "llvm/ExecutionEngine/JITLink/JITLink.h" 19fe6060f1SDimitry Andric #include "llvm/Support/Debug.h" 20fe6060f1SDimitry Andric 21fe6060f1SDimitry Andric #define DEBUG_TYPE "jitlink" 22fe6060f1SDimitry Andric 23fe6060f1SDimitry Andric namespace llvm { 24fe6060f1SDimitry Andric namespace jitlink { 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric struct SectionRangeSymbolDesc { 27fe6060f1SDimitry Andric SectionRangeSymbolDesc() = default; 28fe6060f1SDimitry Andric SectionRangeSymbolDesc(Section &Sec, bool IsStart) 29fe6060f1SDimitry Andric : Sec(&Sec), IsStart(IsStart) {} 30fe6060f1SDimitry Andric Section *Sec = nullptr; 31fe6060f1SDimitry Andric bool IsStart = false; 32fe6060f1SDimitry Andric }; 33fe6060f1SDimitry Andric 34fe6060f1SDimitry Andric /// Pass implementation for the createDefineExternalSectionStartAndEndSymbols 35fe6060f1SDimitry Andric /// function. 36fe6060f1SDimitry Andric template <typename SymbolIdentifierFunction> 37fe6060f1SDimitry Andric class DefineExternalSectionStartAndEndSymbols { 38fe6060f1SDimitry Andric public: 39fe6060f1SDimitry Andric DefineExternalSectionStartAndEndSymbols(SymbolIdentifierFunction F) 40fe6060f1SDimitry Andric : F(std::move(F)) {} 41fe6060f1SDimitry Andric 42fe6060f1SDimitry Andric Error operator()(LinkGraph &G) { 43fe6060f1SDimitry Andric 44fe6060f1SDimitry Andric // This pass will affect the external symbols set, so copy them out into a 45fe6060f1SDimitry Andric // vector and iterate over that. 46fe6060f1SDimitry Andric std::vector<Symbol *> Externals(G.external_symbols().begin(), 47fe6060f1SDimitry Andric G.external_symbols().end()); 48fe6060f1SDimitry Andric 49fe6060f1SDimitry Andric for (auto *Sym : Externals) { 50fe6060f1SDimitry Andric SectionRangeSymbolDesc D = F(G, *Sym); 51fe6060f1SDimitry Andric if (D.Sec) { 52fe6060f1SDimitry Andric auto &SR = getSectionRange(*D.Sec); 53fe6060f1SDimitry Andric if (D.IsStart) { 54fe6060f1SDimitry Andric if (SR.empty()) 55*04eeddc0SDimitry Andric G.makeAbsolute(*Sym, orc::ExecutorAddr()); 56fe6060f1SDimitry Andric else 57fe6060f1SDimitry Andric G.makeDefined(*Sym, *SR.getFirstBlock(), 0, 0, Linkage::Strong, 58fe6060f1SDimitry Andric Scope::Local, false); 59fe6060f1SDimitry Andric } else { 60fe6060f1SDimitry Andric if (SR.empty()) 61*04eeddc0SDimitry Andric G.makeAbsolute(*Sym, orc::ExecutorAddr()); 62fe6060f1SDimitry Andric else 63fe6060f1SDimitry Andric G.makeDefined(*Sym, *SR.getLastBlock(), 64fe6060f1SDimitry Andric SR.getLastBlock()->getSize(), 0, Linkage::Strong, 65fe6060f1SDimitry Andric Scope::Local, false); 66fe6060f1SDimitry Andric } 67fe6060f1SDimitry Andric } 68fe6060f1SDimitry Andric } 69fe6060f1SDimitry Andric return Error::success(); 70fe6060f1SDimitry Andric } 71fe6060f1SDimitry Andric 72fe6060f1SDimitry Andric private: 73fe6060f1SDimitry Andric SectionRange &getSectionRange(Section &Sec) { 74fe6060f1SDimitry Andric auto I = SectionRanges.find(&Sec); 75fe6060f1SDimitry Andric if (I == SectionRanges.end()) 76fe6060f1SDimitry Andric I = SectionRanges.insert(std::make_pair(&Sec, SectionRange(Sec))).first; 77fe6060f1SDimitry Andric return I->second; 78fe6060f1SDimitry Andric } 79fe6060f1SDimitry Andric 80fe6060f1SDimitry Andric DenseMap<Section *, SectionRange> SectionRanges; 81fe6060f1SDimitry Andric SymbolIdentifierFunction F; 82fe6060f1SDimitry Andric }; 83fe6060f1SDimitry Andric 84fe6060f1SDimitry Andric /// Returns a JITLink pass (as a function class) that uses the given symbol 85fe6060f1SDimitry Andric /// identification function to identify external section start and end symbols 86fe6060f1SDimitry Andric /// (and their associated Section*s) and transform the identified externals 87fe6060f1SDimitry Andric /// into defined symbols pointing to the start of the first block in the 88fe6060f1SDimitry Andric /// section and the end of the last (start and end symbols for empty sections 89fe6060f1SDimitry Andric /// will be transformed into absolute symbols at address 0). 90fe6060f1SDimitry Andric /// 91fe6060f1SDimitry Andric /// The identification function should be callable as 92fe6060f1SDimitry Andric /// 93fe6060f1SDimitry Andric /// SectionRangeSymbolDesc (LinkGraph &G, Symbol &Sym) 94fe6060f1SDimitry Andric /// 95fe6060f1SDimitry Andric /// If Sym is not a section range start or end symbol then a default 96fe6060f1SDimitry Andric /// constructed SectionRangeSymbolDesc should be returned. If Sym is a start 97fe6060f1SDimitry Andric /// symbol then SectionRangeSymbolDesc(Sec, true), where Sec is a reference to 98fe6060f1SDimitry Andric /// the target Section. If Sym is an end symbol then 99fe6060f1SDimitry Andric /// SectionRangeSymbolDesc(Sec, false) should be returned. 100fe6060f1SDimitry Andric /// 101fe6060f1SDimitry Andric /// This pass should be run in the PostAllocationPass pipeline, at which point 102fe6060f1SDimitry Andric /// all blocks should have been assigned their final addresses. 103fe6060f1SDimitry Andric template <typename SymbolIdentifierFunction> 104fe6060f1SDimitry Andric DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction> 105fe6060f1SDimitry Andric createDefineExternalSectionStartAndEndSymbolsPass( 106fe6060f1SDimitry Andric SymbolIdentifierFunction &&F) { 107fe6060f1SDimitry Andric return DefineExternalSectionStartAndEndSymbols<SymbolIdentifierFunction>( 108fe6060f1SDimitry Andric std::forward<SymbolIdentifierFunction>(F)); 109fe6060f1SDimitry Andric } 110fe6060f1SDimitry Andric 111fe6060f1SDimitry Andric } // end namespace jitlink 112fe6060f1SDimitry Andric } // end namespace llvm 113fe6060f1SDimitry Andric 114fe6060f1SDimitry Andric #undef DEBUG_TYPE 115fe6060f1SDimitry Andric 116fe6060f1SDimitry Andric #endif // LLVM_EXECUTIONENGINE_JITLINK_DEFINEEXTERNALSECTIONSTARTANDENDSYMBOLS_H 117