c++ - Why is my LLVM JIT implementation segfaulting? -


i'm trying implement simple jit compiler using llvm, following along tutorial (http://releases.llvm.org/4.0.1/docs/tutorial/buildingajit1.html), , i'm running segfault. i've rewritten code in form minimal (albeit still kinda long) example. example loops through integers 0 through 9 , each 1 attempts compile function prints integer, add module, execute function, , remove module jit. simulate interactive session in user inputs commands such print 0, print 1, etc.

#include <array> #include <cstdint> #include <iostream> #include <llvm/executionengine/executionengine.h> #include <llvm/executionengine/jitsymbol.h> #include <llvm/executionengine/orc/compileutils.h> #include <llvm/executionengine/orc/ircompilelayer.h> #include <llvm/executionengine/orc/lambdaresolver.h> #include <llvm/executionengine/orc/objectlinkinglayer.h> #include <llvm/executionengine/sectionmemorymanager.h> #include <llvm/executionengine/runtimedyld.h> #include <llvm/ir/basicblock.h> #include <llvm/ir/constants.h> #include <llvm/ir/derivedtypes.h> #include <llvm/ir/function.h> #include <llvm/ir/globalvalue.h> #include <llvm/ir/globalvariable.h> #include <llvm/ir/irbuilder.h> #include <llvm/ir/llvmcontext.h> #include <llvm/ir/legacypassmanager.h> #include <llvm/ir/mangler.h> #include <llvm/ir/module.h> #include <llvm/ir/type.h> #include <llvm/ir/value.h> #include <llvm/ir/verifier.h> #include <llvm/support/dynamiclibrary.h> #include <llvm/support/targetselect.h> #include <llvm/support/raw_ostream.h> #include <llvm/target/targetmachine.h> #include <llvm/transforms/scalar.h> #include <llvm/transforms/scalar/gvn.h> #include <memory> #include <stdexcept> #include <string> #include <utility> #include <vector>  int main() {      llvm::initializenativetarget();     llvm::initializenativetargetasmprinter();     llvm::initializenativetargetasmparser();      auto machine = llvm::enginebuilder().selecttarget();      llvm::orc::objectlinkinglayer<> linking_layer;     llvm::orc::ircompilelayer<llvm::orc::objectlinkinglayer<>> compile_layer(         linking_layer, llvm::orc::simplecompiler(*machine)     );      llvm::llvmcontext context;     llvm::irbuilder<> builder(context);     auto layout = machine->createdatalayout();      auto module  = std::make_unique<llvm::module>("module", context);      auto manager = std::make_unique<llvm::legacy::functionpassmanager>(         module.get()     );     (         auto p : {             llvm::createinstructioncombiningpass(),             llvm::createreassociatepass(), llvm::creategvnpass(),             llvm::createcfgsimplificationpass()         }     ) manager->add(p);      module->setdatalayout(layout);      llvm::sys::dynamiclibrary::loadlibrarypermanently(nullptr);      auto index = llvm::constantint::get(context, llvm::apint(8, 0));     std::vector<llvm::constant*> indices = {index, index};      std::string func_name = "func";      (auto = 0; < 10; ++i) {          auto format_str = new llvm::globalvariable(             *module, llvm::arraytype::get(llvm::type::getint8ty(context), 4),             true, llvm::globalvalue::privatelinkage,             llvm::constantdataarray::getstring(context, "%i\n"), "format_str"         );         format_str->setalignment(1);          auto function = llvm::function::create(             llvm::functiontype::get(                 llvm::type::getvoidty(context), std::vector<llvm::type*>{},                 false             ), llvm::function::externallinkage, func_name, module.get()         );          builder.setinsertpoint(             llvm::basicblock::create(context, "entry", function)         );          builder.createcall(             module->getorinsertfunction(                 "printf", llvm::functiontype::get(                     llvm::integertype::getint32ty(context),                     llvm::pointertype::get(llvm::type::getint8ty(context), 0),                     true                 )             ), std::vector<llvm::value*>{                 llvm::constantexpr::getgetelementptr(                     nullptr, format_str, indices                 ), llvm::constantint::get(context, llvm::apint(32, i))             }, "call"         );          builder.createretvoid();          std::string message;         llvm::raw_string_ostream message_stream(message);         if (llvm::verifyfunction(*function, &message_stream))             throw std::runtime_error(message_stream.str());          auto handle = compile_layer.addmoduleset(             std::array<std::unique_ptr<llvm::module>, 1>{std::move(module)},             std::make_unique<llvm::sectionmemorymanager>(),             llvm::orc::createlambdaresolver(                 [&](const std::string& name) {                     auto symbol = compile_layer.findsymbol(name, false);                     return symbol ? symbol : llvm::jitsymbol(nullptr);                 }, [](const std::string& name) {                     auto address = llvm::rtdyldmemorymanager::                         getsymboladdressinprocess(name);                     return address ? llvm::jitsymbol(                         address, llvm::jitsymbolflags::exported                     ) : llvm::jitsymbol(nullptr);                 }             )         );          std::string mangled_name;         llvm::raw_string_ostream mangled_name_stream(mangled_name);         llvm::mangler::getnamewithprefix(             mangled_name_stream, func_name, layout         );          (             reinterpret_cast <void(*)()> (                 static_cast <intptr_t> (                     compile_layer.findsymbol(                         mangled_name_stream.str(), true                     ).getaddress()                 )             )         )();          compile_layer.removemoduleset(handle);      }  } 

the expected output follows.

0 1 2 3 4 5 6 7 8 9 

instead this.

0 segmentation fault (core dumped) 

according gdb, segfault occuring during call llvm::globalvariable::globalvariable. here's backtrace.

#0  0x00007ffcdb8b6541 in llvm::globalvariable::globalvariable(llvm::module&, llvm::type*, bool, llvm::globalvalue::linkagetypes, llvm::constant*, llvm::twine const&, llvm::globalvariable*, llvm::globalvalue::threadlocalmode, unsigned int, bool) () /usr/lib/libllvm-4.0.so #1  0x000000010000698a in main () @ main.cc:83 

i'm using llvm version 4.0.1 , gcc version 7.1.1 , compiling following command.

g++ -std=c++17 main.cc -o main -o0 -wall -wextra -wno-unused-function \     -wno-unused-value -wno-unused-parameter -werror -ggdb             \     `llvm-config --system-libs --libs core` 

i'm hoping llvm veteran can find mistake. thanks, guys!

module initialized before for loop:

 auto module  = std::make_unique<llvm::module>("module", context); 

then in for loop:

for(...) {     auto format_str = new llvm::globalvariable(*module, ...);                                                ^~~~~~~     ...     std::array<std::unique_ptr<llvm::module>, 1>{std::move(module)},                                                  ^~~~~~~~~~~~~~~~~ } 

at first iteration access object owned module (ok) , move it. transfer ownership of managed object away module.

at second iteration access object managed module -> crash (because doesn't have managed object anymore)


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -