"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.2/src/libponyc/codegen/genjit.cc" (3 Feb 2020, 10768 Bytes) of package /linux/misc/ponyc-0.33.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "genjit.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.33.1_vs_0.33.2.

    1 #include "genjit.h"
    2 #include "genexe.h"
    3 #include "genopt.h"
    4 
    5 #if PONY_LLVM >= 700
    6 
    7 #include "llvm_config_begin.h"
    8 #  include <llvm/ExecutionEngine/ExecutionEngine.h>
    9 #  include <llvm/ExecutionEngine/JITSymbol.h>
   10 #  include <llvm/ExecutionEngine/SectionMemoryManager.h>
   11 #  include <llvm/ExecutionEngine/Orc/CompileUtils.h>
   12 #  include <llvm/ExecutionEngine/Orc/Core.h>
   13 #  include <llvm/ExecutionEngine/Orc/Legacy.h>
   14 #  include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
   15 #  include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
   16 #  include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
   17 #  include <llvm/IR/DataLayout.h>
   18 #  include <llvm/IR/Mangler.h>
   19 #  include <llvm/Support/Error.h>
   20 #  include <llvm/Target/TargetMachine.h>
   21 #include "llvm_config_end.h"
   22 
   23 using namespace llvm;
   24 using namespace llvm::orc;
   25 
   26 #if PONY_LLVM >= 800
   27 
   28 class PonyJIT
   29 {
   30   ExecutionSession _es;
   31   RTDyldObjectLinkingLayer _obj_layer;
   32   IRCompileLayer _compile_layer;
   33 
   34   DataLayout _dl;
   35   MangleAndInterner _mangle;
   36   ThreadSafeContext _ctx;
   37 
   38 public:
   39   PonyJIT(JITTargetMachineBuilder jtmb, DataLayout dl) :
   40     _es(),
   41     _obj_layer(_es, []() { return llvm::make_unique<SectionMemoryManager>();}),
   42     _compile_layer(_es, _obj_layer, ConcurrentIRCompiler(std::move(jtmb))),
   43     _dl(std::move(dl)),
   44     _mangle(_es, _dl),
   45     _ctx(llvm::make_unique<LLVMContext>())
   46   {
   47 #if PONY_LLVM < 900
   48     _es.getMainJITDylib().setGenerator(
   49       cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(_dl)));
   50 #else
   51     _es.getMainJITDylib().setGenerator(
   52       cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(
   53         _dl.getGlobalPrefix())));
   54 #endif
   55 
   56 #if (PONY_LLVM >= 800) && defined(PLATFORM_IS_WINDOWS)
   57     _obj_layer.setOverrideObjectFlagsWithResponsibilityFlags(true);
   58 #endif
   59   }
   60 
   61   static Expected<std::unique_ptr<PonyJIT>> create()
   62   {
   63     auto jtmb = JITTargetMachineBuilder::detectHost();
   64     if (!jtmb)
   65       return jtmb.takeError();
   66 
   67     auto dl = jtmb->getDefaultDataLayoutForTarget();
   68     if (!dl)
   69       return dl.takeError();
   70 
   71     return llvm::make_unique<PonyJIT>(std::move(*jtmb), std::move(*dl));
   72   }
   73 
   74   Error addModule(std::unique_ptr<Module> module)
   75   {
   76     return _compile_layer.add(_es.getMainJITDylib(),
   77       ThreadSafeModule(std::move(module), _ctx));
   78   }
   79 
   80   Expected<JITEvaluatedSymbol> lookup(StringRef name)
   81   {
   82     return _es.lookup({&_es.getMainJITDylib()}, _mangle(name.str()));
   83   }
   84 
   85   JITTargetAddress getSymbolAddress(const char* name)
   86   {
   87     auto symbol = lookup(name);
   88     if (!symbol)
   89       return 0;
   90 
   91     return symbol->getAddress();
   92   }
   93 };
   94 
   95 #else
   96 
   97 class PonyJIT
   98 {
   99   ExecutionSession _es;
  100   std::shared_ptr<SymbolResolver> _sr;
  101   std::unique_ptr<TargetMachine> _tm;
  102   const DataLayout _dl;
  103   RTDyldObjectLinkingLayer _obj_layer;
  104   IRCompileLayer<decltype(_obj_layer), SimpleCompiler> _compile_layer;
  105 
  106 public:
  107   Error error;
  108 
  109   PonyJIT() :
  110     _es(),
  111     _sr(createLegacyLookupResolver(_es,
  112       [this](const std::string& name) -> JITSymbol
  113       {
  114         auto symbol = _compile_layer.findSymbol(name, false);
  115         if (symbol) return symbol;
  116 
  117         auto err = symbol.takeError();
  118         if (err) return JITSymbol(std::move(err));
  119 
  120         auto symaddr = RTDyldMemoryManager::getSymbolAddressInProcess(name);
  121         if (symaddr)
  122           return JITSymbol(symaddr, JITSymbolFlags::Exported);
  123 
  124         return nullptr;
  125       },
  126       [this](Error err)
  127       {
  128         error = std::move(err);
  129       })),
  130     _tm(EngineBuilder().selectTarget()),
  131     _dl(_tm->createDataLayout()),
  132     _obj_layer(_es,
  133       [this](VModuleKey)
  134       {
  135         return RTDyldObjectLinkingLayer::Resources
  136         {
  137           std::make_shared<SectionMemoryManager>(), _sr
  138         };
  139       }),
  140     _compile_layer(_obj_layer, SimpleCompiler(*_tm)),
  141     error(Error::success())
  142   {
  143     llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
  144   }
  145 
  146   VModuleKey addModule(std::unique_ptr<Module> module)
  147   {
  148     VModuleKey key = _es.allocateVModule();
  149     cantFail(_compile_layer.addModule(key, std::move(module)));
  150     return key;
  151   }
  152 
  153   JITTargetAddress getSymbolAddress(const std::string& name)
  154   {
  155     std::string mangled;
  156     raw_string_ostream mangled_stream(mangled);
  157     Mangler::getNameWithPrefix(mangled_stream, name, _dl);
  158     JITSymbol symbol = _compile_layer.findSymbol(mangled_stream.str(), false);
  159     return cantFail(symbol.getAddress());
  160   }
  161 };
  162 #endif
  163 
  164 bool gen_jit_and_run(compile_t* c, int* exit_code, jit_symbol_t* symbols,
  165   size_t symbol_count)
  166 {
  167   reach_type_t* t_main = reach_type_name(c->reach, "Main");
  168   reach_type_t* t_env = reach_type_name(c->reach, "Env");
  169 
  170   if ((t_main == NULL) || (t_env == NULL))
  171     return false;
  172 
  173   gen_main(c, t_main, t_env);
  174 
  175   if (!genopt(c, true))
  176     return false;
  177 
  178   if (LLVMVerifyModule(c->module, LLVMReturnStatusAction, NULL) != 0)
  179     return false;
  180 
  181 #if PONY_LLVM >= 800
  182   auto jit = cantFail(PonyJIT::create());
  183 
  184   auto err = jit->addModule(std::unique_ptr<Module>(unwrap(c->module)));
  185   if (err)
  186   {
  187     errorf(c->opt->check.errors, nullptr, "LLVM ORC JIT Error");
  188     return false;
  189   }
  190   c->module = nullptr;
  191 
  192 #else
  193   auto jit = llvm::make_unique<PonyJIT>();
  194   jit->addModule(std::unique_ptr<Module>(llvm::unwrap(c->module)));
  195   c->module = nullptr;
  196 
  197   if (jit->error)
  198   {
  199     errorf(c->opt->check.errors, nullptr, "LLVM ORC JIT Error");
  200     return false;
  201   }
  202 #endif
  203 
  204   for (size_t i = 0; i < symbol_count; i++)
  205   {
  206     void* address = (void*)jit->getSymbolAddress(symbols[i].name);
  207     if (address == nullptr)
  208       return false;
  209 
  210     memcpy(symbols[i].address, address, symbols[i].size);
  211   }
  212 
  213   auto main = reinterpret_cast<int(*)(int, const char**, const char**)>(
  214     jit->getSymbolAddress("main")
  215   );
  216 
  217   if (main == nullptr)
  218     return false;
  219 
  220   const char* argv[] = { "ponyjit", nullptr };
  221   const char* envp = nullptr;
  222 
  223   int ec = main(1, argv, &envp);
  224 
  225   if (exit_code != nullptr)
  226     *exit_code = ec;
  227   return true;
  228 }
  229 
  230 #else
  231 
  232 #include "llvm_config_begin.h"
  233 #  include <llvm/IR/Mangler.h>
  234 #  include <llvm/IR/Module.h>
  235 #  include <llvm/ExecutionEngine/Orc/CompileUtils.h>
  236 #  include <llvm/ExecutionEngine/Orc/IRCompileLayer.h>
  237 #  include <llvm/ExecutionEngine/Orc/LambdaResolver.h>
  238 #  if PONY_LLVM >= 500
  239 #    include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
  240 #  else
  241 #    include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
  242 #  endif
  243 #  include <llvm/ExecutionEngine/SectionMemoryManager.h>
  244 #include "llvm_config_end.h"
  245 
  246 namespace orc = llvm::orc;
  247 
  248 #if PONY_LLVM >= 500
  249 using LinkingLayerType = orc::RTDyldObjectLinkingLayer;
  250 using CompileLayerType = orc::IRCompileLayer<LinkingLayerType,
  251   orc::SimpleCompiler>;
  252 using ModuleHandleType = CompileLayerType::ModuleHandleT;
  253 #else
  254 using LinkingLayerType = orc::ObjectLinkingLayer<orc::DoNothingOnNotifyLoaded>;
  255 using CompileLayerType = orc::IRCompileLayer<LinkingLayerType>;
  256 using ModuleHandleType = CompileLayerType::ModuleSetHandleT;
  257 #endif
  258 
  259 static std::string mangle_symbol(llvm::Mangler& mangler,
  260   const llvm::GlobalValue* val)
  261 {
  262   std::string mangled{};
  263   llvm::raw_string_ostream mangle_stream{mangled};
  264   mangler.getNameWithPrefix(mangle_stream, val, false);
  265   mangle_stream.flush();
  266   return mangled;
  267 }
  268 
  269 static void* find_symbol(llvm::Module& module, CompileLayerType& compile_layer,
  270   ModuleHandleType handle, llvm::Mangler& mangler, std::string const& name)
  271 {
  272   const llvm::GlobalValue* val = module.getNamedGlobal(name);
  273 
  274   if(val == nullptr)
  275     val = module.getFunction(name);
  276 
  277   if(val == nullptr)
  278     return nullptr;
  279 
  280   auto local_symbol = compile_layer.findSymbolIn(handle,
  281    mangle_symbol(mangler, val), false);
  282 
  283   if(!local_symbol)
  284     return nullptr;
  285 
  286   auto address = local_symbol.getAddress();
  287 
  288 #if PONY_LLVM >= 500
  289   if(!address)
  290     return nullptr;
  291 
  292   return reinterpret_cast<void*>(address.get());
  293 #else
  294   return reinterpret_cast<void*>(address);
  295 #endif
  296 }
  297 
  298 bool gen_jit_and_run(compile_t* c, int* exit_code, jit_symbol_t* symbols,
  299   size_t symbol_count)
  300 {
  301   reach_type_t* t_main = reach_type_name(c->reach, "Main");
  302   reach_type_t* t_env = reach_type_name(c->reach, "Env");
  303 
  304   if ((t_main == NULL) || (t_env == NULL))
  305     return false;
  306 
  307   gen_main(c, t_main, t_env);
  308 
  309   if (!genopt(c, true))
  310     return false;
  311 
  312   if (LLVMVerifyModule(c->module, LLVMReturnStatusAction, NULL) != 0)
  313     return false;
  314 
  315   // The Orc JIT wants the module in a shared_ptr, but we don't want to transfer
  316   // ownership to that shared_ptr. Use an empty deleter so that the module
  317   // doesn't get freed when the shared_ptr is destroyed.
  318   auto noop_deleter = [](void* p){ (void)p; };
  319   std::shared_ptr<llvm::Module> module{llvm::unwrap(c->module), noop_deleter};
  320 
  321   auto machine = reinterpret_cast<llvm::TargetMachine*>(c->machine);
  322 
  323   auto mem_mgr = std::make_shared<llvm::SectionMemoryManager>();
  324 
  325   LinkingLayerType linking_layer{
  326 #if PONY_LLVM >= 500
  327     [&mem_mgr]{ return mem_mgr; }
  328 #endif
  329   };
  330 
  331   CompileLayerType compile_layer{linking_layer, orc::SimpleCompiler{*machine}};
  332 
  333   auto local_lookup = [&compile_layer](llvm::StringRef name)
  334   {
  335 #if PONY_LLVM >= 400
  336     return compile_layer.findSymbol(name, false);
  337 #else
  338     if(auto sym = compile_layer.findSymbol(name, false))
  339       return sym.toRuntimeDyldSymbol();
  340 
  341     return llvm::RuntimeDyld::SymbolInfo{nullptr};
  342 #endif
  343   };
  344 
  345   auto external_lookup = [
  346 #if PONY_LLVM >= 500
  347     &mem_mgr
  348 #endif
  349   ](llvm::StringRef name)
  350   {
  351 #if PONY_LLVM >= 500
  352     return mem_mgr->findSymbol(name);
  353 #else
  354 #  if PONY_LLVM >= 400
  355     using SymType = llvm::JITSymbol;
  356 #  else
  357     using SymType = llvm::RuntimeDyld::SymbolInfo;
  358 #  endif
  359 
  360     if(auto sym = llvm::RTDyldMemoryManager::getSymbolAddressInProcess(name))
  361       return SymType{sym, llvm::JITSymbolFlags::Exported};
  362 
  363     return SymType{nullptr};
  364 #endif
  365   };
  366 
  367   auto resolver = orc::createLambdaResolver(local_lookup, external_lookup);
  368 #if PONY_LLVM >= 500
  369   auto maybe_handle = compile_layer.addModule(module, resolver);
  370 
  371   if(!maybe_handle)
  372     return false;
  373 
  374   auto handle = maybe_handle.get();
  375 #else
  376   std::vector<decltype(module)> module_set{module};
  377   auto handle = compile_layer.addModuleSet(std::move(module_set), mem_mgr,
  378     std::move(resolver));
  379 #endif
  380 
  381   llvm::Mangler mangler{};
  382 
  383   for(size_t i = 0; i < symbol_count; i++)
  384   {
  385     auto address = find_symbol(*module, compile_layer, handle, mangler,
  386       symbols[i].name);
  387 
  388     if(address == nullptr)
  389       return false;
  390 
  391     memcpy(symbols[i].address, address, symbols[i].size);
  392   }
  393 
  394   auto local_main = reinterpret_cast<int(*)(int, const char**, const char**)>(
  395     find_symbol(*module, compile_layer, handle, mangler, "main"));
  396 
  397   if(local_main == nullptr)
  398     return false;
  399 
  400   const char* argv[] = {"ponyjit", nullptr};
  401   const char* envp = NULL;
  402 
  403   int ec = local_main(1, argv, &envp);
  404 
  405   if(exit_code != nullptr)
  406     *exit_code = ec;
  407 
  408   return true;
  409 }
  410 
  411 #endif