117 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--------- 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
 |