Home | History | Annotate | Line # | Download | only in Orc
      1 //===----- LLJIT.h -- An ORC-based JIT for compiling LLVM IR ----*- 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 // An ORC-based JIT for compiling LLVM IR.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_EXECUTIONENGINE_ORC_LLJIT_H
     14 #define LLVM_EXECUTIONENGINE_ORC_LLJIT_H
     15 
     16 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
     17 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
     18 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
     19 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
     20 #include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
     21 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
     22 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
     23 #include "llvm/Support/Debug.h"
     24 #include "llvm/Support/ThreadPool.h"
     25 
     26 namespace llvm {
     27 namespace orc {
     28 
     29 class LLJITBuilderState;
     30 class LLLazyJITBuilderState;
     31 class ObjectTransformLayer;
     32 class TargetProcessControl;
     33 
     34 /// A pre-fabricated ORC JIT stack that can serve as an alternative to MCJIT.
     35 ///
     36 /// Create instances using LLJITBuilder.
     37 class LLJIT {
     38   template <typename, typename, typename> friend class LLJITBuilderSetters;
     39 
     40   friend void setUpGenericLLVMIRPlatform(LLJIT &J);
     41 
     42 public:
     43   /// Initializer support for LLJIT.
     44   class PlatformSupport {
     45   public:
     46     virtual ~PlatformSupport();
     47 
     48     virtual Error initialize(JITDylib &JD) = 0;
     49 
     50     virtual Error deinitialize(JITDylib &JD) = 0;
     51 
     52   protected:
     53     static void setInitTransform(LLJIT &J,
     54                                  IRTransformLayer::TransformFunction T);
     55   };
     56 
     57   /// Destruct this instance. If a multi-threaded instance, waits for all
     58   /// compile threads to complete.
     59   ~LLJIT();
     60 
     61   /// Returns the ExecutionSession for this instance.
     62   ExecutionSession &getExecutionSession() { return *ES; }
     63 
     64   /// Returns a reference to the triple for this instance.
     65   const Triple &getTargetTriple() const { return TT; }
     66 
     67   /// Returns a reference to the DataLayout for this instance.
     68   const DataLayout &getDataLayout() const { return DL; }
     69 
     70   /// Returns a reference to the JITDylib representing the JIT'd main program.
     71   JITDylib &getMainJITDylib() { return *Main; }
     72 
     73   /// Returns the JITDylib with the given name, or nullptr if no JITDylib with
     74   /// that name exists.
     75   JITDylib *getJITDylibByName(StringRef Name) {
     76     return ES->getJITDylibByName(Name);
     77   }
     78 
     79   /// Create a new JITDylib with the given name and return a reference to it.
     80   ///
     81   /// JITDylib names must be unique. If the given name is derived from user
     82   /// input or elsewhere in the environment then the client should check
     83   /// (e.g. by calling getJITDylibByName) that the given name is not already in
     84   /// use.
     85   Expected<JITDylib &> createJITDylib(std::string Name) {
     86     return ES->createJITDylib(std::move(Name));
     87   }
     88 
     89   /// Adds an IR module with the given ResourceTracker.
     90   Error addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM);
     91 
     92   /// Adds an IR module to the given JITDylib.
     93   Error addIRModule(JITDylib &JD, ThreadSafeModule TSM);
     94 
     95   /// Adds an IR module to the Main JITDylib.
     96   Error addIRModule(ThreadSafeModule TSM) {
     97     return addIRModule(*Main, std::move(TSM));
     98   }
     99 
    100   /// Adds an object file to the given JITDylib.
    101   Error addObjectFile(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> Obj);
    102 
    103   /// Adds an object file to the given JITDylib.
    104   Error addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj);
    105 
    106   /// Adds an object file to the given JITDylib.
    107   Error addObjectFile(std::unique_ptr<MemoryBuffer> Obj) {
    108     return addObjectFile(*Main, std::move(Obj));
    109   }
    110 
    111   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
    112   /// look up symbols based on their IR name use the lookup function instead).
    113   Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
    114                                                    SymbolStringPtr Name);
    115 
    116   /// Look up a symbol in JITDylib JD by the symbol's linker-mangled name (to
    117   /// look up symbols based on their IR name use the lookup function instead).
    118   Expected<JITEvaluatedSymbol> lookupLinkerMangled(JITDylib &JD,
    119                                                    StringRef Name) {
    120     return lookupLinkerMangled(JD, ES->intern(Name));
    121   }
    122 
    123   /// Look up a symbol in the main JITDylib by the symbol's linker-mangled name
    124   /// (to look up symbols based on their IR name use the lookup function
    125   /// instead).
    126   Expected<JITEvaluatedSymbol> lookupLinkerMangled(StringRef Name) {
    127     return lookupLinkerMangled(*Main, Name);
    128   }
    129 
    130   /// Look up a symbol in JITDylib JD based on its IR symbol name.
    131   Expected<JITEvaluatedSymbol> lookup(JITDylib &JD, StringRef UnmangledName) {
    132     return lookupLinkerMangled(JD, mangle(UnmangledName));
    133   }
    134 
    135   /// Look up a symbol in the main JITDylib based on its IR symbol name.
    136   Expected<JITEvaluatedSymbol> lookup(StringRef UnmangledName) {
    137     return lookup(*Main, UnmangledName);
    138   }
    139 
    140   /// Set the PlatformSupport instance.
    141   void setPlatformSupport(std::unique_ptr<PlatformSupport> PS) {
    142     this->PS = std::move(PS);
    143   }
    144 
    145   /// Get the PlatformSupport instance.
    146   PlatformSupport *getPlatformSupport() { return PS.get(); }
    147 
    148   /// Run the initializers for the given JITDylib.
    149   Error initialize(JITDylib &JD) {
    150     DEBUG_WITH_TYPE("orc", {
    151       dbgs() << "LLJIT running initializers for JITDylib \"" << JD.getName()
    152              << "\"\n";
    153     });
    154     assert(PS && "PlatformSupport must be set to run initializers.");
    155     return PS->initialize(JD);
    156   }
    157 
    158   /// Run the deinitializers for the given JITDylib.
    159   Error deinitialize(JITDylib &JD) {
    160     DEBUG_WITH_TYPE("orc", {
    161       dbgs() << "LLJIT running deinitializers for JITDylib \"" << JD.getName()
    162              << "\"\n";
    163     });
    164     assert(PS && "PlatformSupport must be set to run initializers.");
    165     return PS->deinitialize(JD);
    166   }
    167 
    168   /// Returns a reference to the ObjLinkingLayer
    169   ObjectLayer &getObjLinkingLayer() { return *ObjLinkingLayer; }
    170 
    171   /// Returns a reference to the object transform layer.
    172   ObjectTransformLayer &getObjTransformLayer() { return *ObjTransformLayer; }
    173 
    174   /// Returns a reference to the IR transform layer.
    175   IRTransformLayer &getIRTransformLayer() { return *TransformLayer; }
    176 
    177   /// Returns a reference to the IR compile layer.
    178   IRCompileLayer &getIRCompileLayer() { return *CompileLayer; }
    179 
    180   /// Returns a linker-mangled version of UnmangledName.
    181   std::string mangle(StringRef UnmangledName) const;
    182 
    183   /// Returns an interned, linker-mangled version of UnmangledName.
    184   SymbolStringPtr mangleAndIntern(StringRef UnmangledName) const {
    185     return ES->intern(mangle(UnmangledName));
    186   }
    187 
    188 protected:
    189   static Expected<std::unique_ptr<ObjectLayer>>
    190   createObjectLinkingLayer(LLJITBuilderState &S, ExecutionSession &ES);
    191 
    192   static Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>
    193   createCompileFunction(LLJITBuilderState &S, JITTargetMachineBuilder JTMB);
    194 
    195   /// Create an LLJIT instance with a single compile thread.
    196   LLJIT(LLJITBuilderState &S, Error &Err);
    197 
    198   Error applyDataLayout(Module &M);
    199 
    200   void recordCtorDtors(Module &M);
    201 
    202   std::unique_ptr<ExecutionSession> ES;
    203   std::unique_ptr<PlatformSupport> PS;
    204 
    205   JITDylib *Main = nullptr;
    206 
    207   DataLayout DL;
    208   Triple TT;
    209   std::unique_ptr<ThreadPool> CompileThreads;
    210 
    211   std::unique_ptr<ObjectLayer> ObjLinkingLayer;
    212   std::unique_ptr<ObjectTransformLayer> ObjTransformLayer;
    213   std::unique_ptr<IRCompileLayer> CompileLayer;
    214   std::unique_ptr<IRTransformLayer> TransformLayer;
    215   std::unique_ptr<IRTransformLayer> InitHelperTransformLayer;
    216 };
    217 
    218 /// An extended version of LLJIT that supports lazy function-at-a-time
    219 /// compilation of LLVM IR.
    220 class LLLazyJIT : public LLJIT {
    221   template <typename, typename, typename> friend class LLJITBuilderSetters;
    222 
    223 public:
    224 
    225   /// Sets the partition function.
    226   void
    227   setPartitionFunction(CompileOnDemandLayer::PartitionFunction Partition) {
    228     CODLayer->setPartitionFunction(std::move(Partition));
    229   }
    230 
    231   /// Returns a reference to the on-demand layer.
    232   CompileOnDemandLayer &getCompileOnDemandLayer() { return *CODLayer; }
    233 
    234   /// Add a module to be lazily compiled to JITDylib JD.
    235   Error addLazyIRModule(JITDylib &JD, ThreadSafeModule M);
    236 
    237   /// Add a module to be lazily compiled to the main JITDylib.
    238   Error addLazyIRModule(ThreadSafeModule M) {
    239     return addLazyIRModule(*Main, std::move(M));
    240   }
    241 
    242 private:
    243 
    244   // Create a single-threaded LLLazyJIT instance.
    245   LLLazyJIT(LLLazyJITBuilderState &S, Error &Err);
    246 
    247   std::unique_ptr<LazyCallThroughManager> LCTMgr;
    248   std::unique_ptr<CompileOnDemandLayer> CODLayer;
    249 };
    250 
    251 class LLJITBuilderState {
    252 public:
    253   using ObjectLinkingLayerCreator =
    254       std::function<Expected<std::unique_ptr<ObjectLayer>>(ExecutionSession &,
    255                                                            const Triple &)>;
    256 
    257   using CompileFunctionCreator =
    258       std::function<Expected<std::unique_ptr<IRCompileLayer::IRCompiler>>(
    259           JITTargetMachineBuilder JTMB)>;
    260 
    261   using PlatformSetupFunction = std::function<Error(LLJIT &J)>;
    262 
    263   std::unique_ptr<ExecutionSession> ES;
    264   Optional<JITTargetMachineBuilder> JTMB;
    265   Optional<DataLayout> DL;
    266   ObjectLinkingLayerCreator CreateObjectLinkingLayer;
    267   CompileFunctionCreator CreateCompileFunction;
    268   PlatformSetupFunction SetUpPlatform;
    269   unsigned NumCompileThreads = 0;
    270   TargetProcessControl *TPC = nullptr;
    271 
    272   /// Called prior to JIT class construcion to fix up defaults.
    273   Error prepareForConstruction();
    274 };
    275 
    276 template <typename JITType, typename SetterImpl, typename State>
    277 class LLJITBuilderSetters {
    278 public:
    279 
    280   /// Set an ExecutionSession for this instance.
    281   SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) {
    282     impl().ES = std::move(ES);
    283     return impl();
    284   }
    285 
    286   /// Set the JITTargetMachineBuilder for this instance.
    287   ///
    288   /// If this method is not called, JITTargetMachineBuilder::detectHost will be
    289   /// used to construct a default target machine builder for the host platform.
    290   SetterImpl &setJITTargetMachineBuilder(JITTargetMachineBuilder JTMB) {
    291     impl().JTMB = std::move(JTMB);
    292     return impl();
    293   }
    294 
    295   /// Return a reference to the JITTargetMachineBuilder.
    296   ///
    297   Optional<JITTargetMachineBuilder> &getJITTargetMachineBuilder() {
    298     return impl().JTMB;
    299   }
    300 
    301   /// Set a DataLayout for this instance. If no data layout is specified then
    302   /// the target's default data layout will be used.
    303   SetterImpl &setDataLayout(Optional<DataLayout> DL) {
    304     impl().DL = std::move(DL);
    305     return impl();
    306   }
    307 
    308   /// Set an ObjectLinkingLayer creation function.
    309   ///
    310   /// If this method is not called, a default creation function will be used
    311   /// that will construct an RTDyldObjectLinkingLayer.
    312   SetterImpl &setObjectLinkingLayerCreator(
    313       LLJITBuilderState::ObjectLinkingLayerCreator CreateObjectLinkingLayer) {
    314     impl().CreateObjectLinkingLayer = std::move(CreateObjectLinkingLayer);
    315     return impl();
    316   }
    317 
    318   /// Set a CompileFunctionCreator.
    319   ///
    320   /// If this method is not called, a default creation function wil be used
    321   /// that will construct a basic IR compile function that is compatible with
    322   /// the selected number of threads (SimpleCompiler for '0' compile threads,
    323   /// ConcurrentIRCompiler otherwise).
    324   SetterImpl &setCompileFunctionCreator(
    325       LLJITBuilderState::CompileFunctionCreator CreateCompileFunction) {
    326     impl().CreateCompileFunction = std::move(CreateCompileFunction);
    327     return impl();
    328   }
    329 
    330   /// Set up an PlatformSetupFunction.
    331   ///
    332   /// If this method is not called then setUpGenericLLVMIRPlatform
    333   /// will be used to configure the JIT's platform support.
    334   SetterImpl &
    335   setPlatformSetUp(LLJITBuilderState::PlatformSetupFunction SetUpPlatform) {
    336     impl().SetUpPlatform = std::move(SetUpPlatform);
    337     return impl();
    338   }
    339 
    340   /// Set the number of compile threads to use.
    341   ///
    342   /// If set to zero, compilation will be performed on the execution thread when
    343   /// JITing in-process. If set to any other number N, a thread pool of N
    344   /// threads will be created for compilation.
    345   ///
    346   /// If this method is not called, behavior will be as if it were called with
    347   /// a zero argument.
    348   SetterImpl &setNumCompileThreads(unsigned NumCompileThreads) {
    349     impl().NumCompileThreads = NumCompileThreads;
    350     return impl();
    351   }
    352 
    353   /// Set a TargetProcessControl object.
    354   ///
    355   /// If the platform uses ObjectLinkingLayer by default and no
    356   /// ObjectLinkingLayerCreator has been set then the TargetProcessControl
    357   /// object will be used to supply the memory manager for the
    358   /// ObjectLinkingLayer.
    359   SetterImpl &setTargetProcessControl(TargetProcessControl &TPC) {
    360     impl().TPC = &TPC;
    361     return impl();
    362   }
    363 
    364   /// Create an instance of the JIT.
    365   Expected<std::unique_ptr<JITType>> create() {
    366     if (auto Err = impl().prepareForConstruction())
    367       return std::move(Err);
    368 
    369     Error Err = Error::success();
    370     std::unique_ptr<JITType> J(new JITType(impl(), Err));
    371     if (Err)
    372       return std::move(Err);
    373     return std::move(J);
    374   }
    375 
    376 protected:
    377   SetterImpl &impl() { return static_cast<SetterImpl &>(*this); }
    378 };
    379 
    380 /// Constructs LLJIT instances.
    381 class LLJITBuilder
    382     : public LLJITBuilderState,
    383       public LLJITBuilderSetters<LLJIT, LLJITBuilder, LLJITBuilderState> {};
    384 
    385 class LLLazyJITBuilderState : public LLJITBuilderState {
    386   friend class LLLazyJIT;
    387 
    388 public:
    389   using IndirectStubsManagerBuilderFunction =
    390       std::function<std::unique_ptr<IndirectStubsManager>()>;
    391 
    392   Triple TT;
    393   JITTargetAddress LazyCompileFailureAddr = 0;
    394   std::unique_ptr<LazyCallThroughManager> LCTMgr;
    395   IndirectStubsManagerBuilderFunction ISMBuilder;
    396 
    397   Error prepareForConstruction();
    398 };
    399 
    400 template <typename JITType, typename SetterImpl, typename State>
    401 class LLLazyJITBuilderSetters
    402     : public LLJITBuilderSetters<JITType, SetterImpl, State> {
    403 public:
    404   /// Set the address in the target address to call if a lazy compile fails.
    405   ///
    406   /// If this method is not called then the value will default to 0.
    407   SetterImpl &setLazyCompileFailureAddr(JITTargetAddress Addr) {
    408     this->impl().LazyCompileFailureAddr = Addr;
    409     return this->impl();
    410   }
    411 
    412   /// Set the lazy-callthrough manager.
    413   ///
    414   /// If this method is not called then a default, in-process lazy callthrough
    415   /// manager for the host platform will be used.
    416   SetterImpl &
    417   setLazyCallthroughManager(std::unique_ptr<LazyCallThroughManager> LCTMgr) {
    418     this->impl().LCTMgr = std::move(LCTMgr);
    419     return this->impl();
    420   }
    421 
    422   /// Set the IndirectStubsManager builder function.
    423   ///
    424   /// If this method is not called then a default, in-process
    425   /// IndirectStubsManager builder for the host platform will be used.
    426   SetterImpl &setIndirectStubsManagerBuilder(
    427       LLLazyJITBuilderState::IndirectStubsManagerBuilderFunction ISMBuilder) {
    428     this->impl().ISMBuilder = std::move(ISMBuilder);
    429     return this->impl();
    430   }
    431 };
    432 
    433 /// Constructs LLLazyJIT instances.
    434 class LLLazyJITBuilder
    435     : public LLLazyJITBuilderState,
    436       public LLLazyJITBuilderSetters<LLLazyJIT, LLLazyJITBuilder,
    437                                      LLLazyJITBuilderState> {};
    438 
    439 /// Configure the LLJIT instance to scrape modules for llvm.global_ctors and
    440 /// llvm.global_dtors variables and (if present) build initialization and
    441 /// deinitialization functions. Platform specific initialization configurations
    442 /// should be preferred where available.
    443 void setUpGenericLLVMIRPlatform(LLJIT &J);
    444 
    445 /// Configure the LLJIT instance to use MachOPlatform support.
    446 ///
    447 /// Warning: MachOPlatform *requires* that LLJIT be configured to use
    448 /// ObjectLinkingLayer (default on platforms supported by JITLink). If
    449 /// MachOPlatform is used with RTDyldObjectLinkingLayer it will result in
    450 /// undefined behavior).
    451 ///
    452 /// MachOPlatform installs an ObjectLinkingLayer plugin to scrape initializers
    453 /// from the __mod_inits section. It also provides interposes for the dlfcn
    454 /// functions (dlopen, dlclose, dlsym, dlerror) that work for JITDylibs as
    455 /// well as regular libraries (JITDylibs will be preferenced, so make sure
    456 /// your JITDylib names do not shadow any real library paths).
    457 Error setUpMachOPlatform(LLJIT &J);
    458 
    459 /// Configure the LLJIT instance to disable platform support explicitly. This is
    460 /// useful in two cases: for platforms that don't have such requirements and for
    461 /// platforms, that we have no explicit support yet and that don't work well
    462 /// with the generic IR platform.
    463 Error setUpInactivePlatform(LLJIT &J);
    464 
    465 } // End namespace orc
    466 } // End namespace llvm
    467 
    468 #endif // LLVM_EXECUTIONENGINE_ORC_LLJIT_H
    469