Hi all, I tried to modify Kaleidoscope Tutorial (toy.cpp from llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order to use MCJIT instead of JIT. I get segmentation fault when running toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is in attachment and still works with JIT (when #define USE_MCJIT line is commented out). I read discussions regarding MCJIT in this mailing list, and I understand it that MCJIT currently cannot be used in the same way as JIT. The separate function-by-function (i.e. incremental) compilation approach with getPointerToFunction, like the one used in the Kaleidoscope tutorial, will not work. Is this correct or do I do something wrong in my code ? There was also a discussion about using multi-module approach instead of getPointerToFunction, but it seems that support for this is not yet available. I would like to know if there is any way currently to let Kaleidoscope-style of compilation work with MCJIT, and if no when it will be available ? Also, even if MCJIT does not support currently this compilation style I still not understand why getPointerToFunction returns me a non-NULL pointer ? I expected to get at least assertion or a NULL pointer. Thanks, Dmitri -------------- next part -------------- A non-text attachment was scrubbed... Name: toy.cpp Type: text/x-c++src Size: 33667 bytes Desc: not available URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130603/bb601c0f/attachment.cpp>
Hi Dmitri, You might want to try replacing the call to JMM->invalidInstructionCache() with a call to TheExecutionEngine->finalizeObject(). If you are getting a non-NULL pointer from getPointerToFunction but it crashes when you try to call it, that is most likely because the memory for the generated code has not been marked as executable. That happens inside finalizeObject, which also invalidates the code cache. Even so, this will likely only work in cases where code generation is only invoked once. You are correct that MCJIT won't work in this case because of the function-by-function approach used in the Kaleidoscope example. Basically, with MCJIT once code has been generated for a module nothing else can be added to the Module. Making Kaleidoscope work with MCJIT would require introducing some sort of scheme where a new module was created each time a new function was created. In the current implementation of MCJIT in trunk it is at least theoretically possible to make such a solution work by also creating a new instance of the MCJIT engine for each Module. It is our intention to enhance MCJIT to allow multiple modules to be handled by a single instance, but there would still be the requirement that once code was generated for a Module it couldn't be modified again. There may also be some work necessary in the memory manager to link the modules together. Obviously it wouldn't be a trivial job to modify the Kaleidoscope example to work with MCJIT, but I think it should be possible. I don't have a concrete time frame for when multiple module support will be available in MCJIT. -Andy -----Original Message----- From: Dmitri Rubinstein [mailto:dmitri.rubinstein at googlemail.com] Sent: Monday, June 03, 2013 4:57 AM To: LLVM Dev Cc: Kaylor, Andrew Subject: MCJIT and Kaleidoscope Tutorial Hi all, I tried to modify Kaleidoscope Tutorial (toy.cpp from llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order to use MCJIT instead of JIT. I get segmentation fault when running toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is in attachment and still works with JIT (when #define USE_MCJIT line is commented out). I read discussions regarding MCJIT in this mailing list, and I understand it that MCJIT currently cannot be used in the same way as JIT. The separate function-by-function (i.e. incremental) compilation approach with getPointerToFunction, like the one used in the Kaleidoscope tutorial, will not work. Is this correct or do I do something wrong in my code ? There was also a discussion about using multi-module approach instead of getPointerToFunction, but it seems that support for this is not yet available. I would like to know if there is any way currently to let Kaleidoscope-style of compilation work with MCJIT, and if no when it will be available ? Also, even if MCJIT does not support currently this compilation style I still not understand why getPointerToFunction returns me a non-NULL pointer ? I expected to get at least assertion or a NULL pointer. Thanks, Dmitri
Hi Andrew, Am 04.06.2013 02:13, schrieb Kaylor, Andrew:> Hi Dmitri, > > You might want to try replacing the call to JMM->invalidInstructionCache() with a call to TheExecutionEngine->finalizeObject(). If you are getting a non-NULL pointer from getPointerToFunction but it crashes when you try to call it, that is most likely because the memory for the generated code has not been marked as executable. That happens inside finalizeObject, which also invalidates the code cache.Thanks a lot, this helped. Now I just see "Error: redefinition of function" when I define new function, and this is expected. I am curious about JMM->invalidInstructionCache(), which I found in lli.cpp implementation. lli.cpp contains also call finalizeObject(), I just overlooked it. lli.cpp calls finalizeObject(), which calls applyPermissions, which in turn calls invalidateInstructionCache. So why lli.cpp does call JMM->invalidInstructionCache() explicitely again ? Also I think there is a bug in MCJIT::getPointerToFunction: ... StringRef BaseName = F->getName(); if (BaseName[0] == '\1') ... When BaseName is empty it triggers assertion. For example in Kaleidoscope tutorial an unnamed function is created.> > Even so, this will likely only work in cases where code generation is only invoked once. > > You are correct that MCJIT won't work in this case because of the function-by-function approach used in the Kaleidoscope example. Basically, with MCJIT once code has been generated for a module nothing else can be added to the Module. > > Making Kaleidoscope work with MCJIT would require introducing some sort of scheme where a new module was created each time a new function was created. In the current implementation of MCJIT in trunk it is at least theoretically possible to make such a solution work by also creating a new instance of the MCJIT engine for each Module. It is our intention to enhance MCJIT to allow multiple modules to be handled by a single instance, but there would still be the requirement that once code was generated for a Module it couldn't be modified again. There may also be some work necessary in the memory manager to link the modules together.When I correctly understand this multi-module incremental approach, I would need to create a new module for any new function generated. Since my new function will likely call another previously defined functions, I will need to declare them in the new module too. Their implementations already exist in the module(s) that I created in previous steps. And memory manager will take care of linking object code generated from all my incrementally created modules. I am also using in my code ExecutionEngine::addGlobalMapping for defining functions that are declared in LLVM code but defined in my application. Will this work with MCJIT ?> > Obviously it wouldn't be a trivial job to modify the Kaleidoscope example to work with MCJIT, but I think it should be possible. > > I don't have a concrete time frame for when multiple module support will be available in MCJIT.OK, I will try to make workarounds in my code as long as MCJIT does not support multi-module fully. Thanks, Dmitri> > -Andy > > -----Original Message----- > From: Dmitri Rubinstein [mailto:dmitri.rubinstein at googlemail.com] > Sent: Monday, June 03, 2013 4:57 AM > To: LLVM Dev > Cc: Kaylor, Andrew > Subject: MCJIT and Kaleidoscope Tutorial > > Hi all, > > I tried to modify Kaleidoscope Tutorial (toy.cpp from llvm/examples/Kaleidoscope/Chapter7, LLVM 3.3 release branch) in order to use MCJIT instead of JIT. I get segmentation fault when running toy.cpp with fibonacci example from the tutorial. My modified toy.cpp is in attachment and still works with JIT (when #define USE_MCJIT line is commented out). > > I read discussions regarding MCJIT in this mailing list, and I understand it that MCJIT currently cannot be used in the same way as JIT. The separate function-by-function (i.e. incremental) compilation approach with getPointerToFunction, like the one used in the Kaleidoscope tutorial, will not work. Is this correct or do I do something wrong in my code ? > > There was also a discussion about using multi-module approach instead of getPointerToFunction, but it seems that support for this is not yet available. I would like to know if there is any way currently to let Kaleidoscope-style of compilation work with MCJIT, and if no when it will be available ? > > Also, even if MCJIT does not support currently this compilation style I still not understand why getPointerToFunction returns me a non-NULL pointer ? I expected to get at least assertion or a NULL pointer. > > Thanks, > > Dmitri >
Am 04.06.2013 16:05, schrieb David Tweed:> | I am curious about JMM->invalidInstructionCache(), which I found in > | lli.cpp implementation. lli.cpp contains also call finalizeObject(), I > | just overlooked it. lli.cpp calls finalizeObject(), which calls > | applyPermissions, which in turn calls invalidateInstructionCache. So why > | lli.cpp does call JMM->invalidInstructionCache() explicitely again ? > > My suspicion is it's a historical development; because different > architectures do or don't actually require cache invalidation the calls have > tended not to be initially put in, then added when other architectures > started using the code. When I was doing some cosmetic changes related to > that I didn't touch lli because the impression seemed to be that it was very > little used these days, so erring on the safe side seemed more important > than being completely minimal. In general, nowadays lli is not an example of > the cleanest way to use MCJIT.But then there is no clean example of using MCJIT at all, please correct me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo, and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are not compatible with MCJIT, there is also no tutorial explaining how to use MCJIT. Best, Dmitri> > Cheers, > Dave > > >
The unit tests contain some example usage; check unittests/ExecutionEngine/MCJIT. I don't believe there's an actual tutorial on MCJIT... Dan On 2013-06-04 10:20 AM, "Dmitri Rubinstein" <dmitri.rubinstein at googlemail.com> wrote:> >Am 04.06.2013 16:05, schrieb David Tweed: >> | I am curious about JMM->invalidInstructionCache(), which I found in >> | lli.cpp implementation. lli.cpp contains also call finalizeObject(), I >> | just overlooked it. lli.cpp calls finalizeObject(), which calls >> | applyPermissions, which in turn calls invalidateInstructionCache. So >>why >> | lli.cpp does call JMM->invalidInstructionCache() explicitely again ? >> >> My suspicion is it's a historical development; because different >> architectures do or don't actually require cache invalidation the calls >>have >> tended not to be initially put in, then added when other architectures >> started using the code. When I was doing some cosmetic changes related >>to >> that I didn't touch lli because the impression seemed to be that it was >>very >> little used these days, so erring on the safe side seemed more important >> than being completely minimal. In general, nowadays lli is not an >>example of >> the cleanest way to use MCJIT. > >But then there is no clean example of using MCJIT at all, please correct >me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo, >and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are >not compatible with MCJIT, there is also no tutorial explaining how to >use MCJIT. > >Best, >Dmitri > >> >> Cheers, >> Dave >> >> >> > >_______________________________________________ >LLVM Developers mailing list >LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu >http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Hi Dmitri, You're right. The lli code should be cleaned up. As David said, there was a time when the call to invalidate the instruction cache was necessary. It isn't necessary anymore. -Andy -----Original Message----- From: Dmitri Rubinstein [mailto:dmitri.rubinstein at googlemail.com] Sent: Tuesday, June 04, 2013 7:20 AM To: David Tweed Cc: Kaylor, Andrew; LLVM Dev Subject: Re: [LLVMdev] MCJIT and Kaleidoscope Tutorial Am 04.06.2013 16:05, schrieb David Tweed:> | I am curious about JMM->invalidInstructionCache(), which I found in > | lli.cpp implementation. lli.cpp contains also call finalizeObject(), > | I just overlooked it. lli.cpp calls finalizeObject(), which calls > | applyPermissions, which in turn calls invalidateInstructionCache. So > | why lli.cpp does call JMM->invalidInstructionCache() explicitely again ? > > My suspicion is it's a historical development; because different > architectures do or don't actually require cache invalidation the > calls have tended not to be initially put in, then added when other > architectures started using the code. When I was doing some cosmetic > changes related to that I didn't touch lli because the impression > seemed to be that it was very little used these days, so erring on the > safe side seemed more important than being completely minimal. In > general, nowadays lli is not an example of the cleanest way to use MCJIT.But then there is no clean example of using MCJIT at all, please correct me if I am wrong. I just did a "git grep MCJIT" in the LLVM git repo, and the only tool using MCJIT is lli. Since Kaleidoscope tutorials are not compatible with MCJIT, there is also no tutorial explaining how to use MCJIT. Best, Dmitri> > Cheers, > Dave > > >