<div dir="ltr">Hi Lang,<div><br></div><div>Thanks for the clarification. I solved the dependency by construction a function dependency graph, and sort it. This way, I always process items in the right order.</div><div><br></div><div>I did some more debugging, and found the cause of my issue. I had an incorrect function name <-> cached object mapping. So when I try to resolve the function name, it could not find it in the processed module. All seems fine now, need to do more testing though. </div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 7, 2016 at 11:15 PM, Lang Hames <span dir="ltr"><<a href="mailto:lhames@gmail.com" target="_blank">lhames@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hi Koffie,<div><br></div><div>Your cache class looks good to me. Can you provide a test case?</div><div><br></div><div>Have you added an IR Module for each cached object before finalizing anything? The way MCJIT is written at the moment a Module needs to be present with a definition of each function before the cache is searched (not ideal - we should fix this, but it's how things are at the moment).</div><div><br></div><div>So one way that this could fail is if you start with two modules A and B, where A depends on B:</div><div><br></div><div>A.ll:</div><div><br></div><div><font face="monospace, monospace">declare void @bar </font></div><div><font face="monospace, monospace">define void @foo ... {</font></div><div><font face="monospace, monospace">  call void @bar</font></div><div><font face="monospace, monospace">  ret void</font></div><div><font face="monospace, monospace">}</font></div><div><br></div><div>B.ll:</div><div><br></div><div><div><font face="monospace, monospace">define void @bar ... {</font></div><div><font face="monospace, monospace">  ret void</font></div><div><font face="monospace, monospace">}</font></div></div><div><br></div><div>If you launch with a cache already containing code for these modules, but only add A.ll (but not B.ll) to the JIT on the second run, the following could happen:</div><div><br></div><div>(1) When searching for @foo, MCJIT::findSymbol (where all the real work for getFunctionAddress is done) won't find anything via findExistingSymbol, so it'll call findModuleForSymbol '@foo', which will return A.ll</div><div>(2) MCJIT::findSymbol will do a cache lookup for A.ll and find your stored A.o</div><div>(3) When you finalize A.o, RuntimeDyld will need the address for @bar, so it'll call (via a few levels of indirection) back to MCJIT::findSymbol again. MCJIT::findSymbol won't find @bar via findExistingSymbol, so it'll call findModuleForSymbol '@bar', but there is no module containing '@bar' (even though there's an object containing it in the cache), so you'll get a nullptr back representing "symbol not found".</div><div><br></div><div>This wouldn't explain the intermittent nature of the failure on its own, but if you're testing by hand in a REPL then success vs. failure will probably depend on will depend on whether you've evaluated '@bar' before '@foo' on any given test run.</div><div><br></div><div>Hope this helps, if not let me know and we'll dig in further.</div><div><br></div><div>- Lang.</div><div><br></div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Thu, Jul 7, 2016 at 2:52 AM, koffie drinker via llvm-dev <span dir="ltr"><<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5"><div dir="ltr">Hi all,<div><br></div><div>I'm trying to add pre-compiled object cache to my run-time.</div><div>I've implemented the object cache as follow:</div><div><br></div><div><div><span style="white-space:pre-wrap">     </span>class EngineObjectCache : public llvm::ObjectCache {</div><div><span style="white-space:pre-wrap">     </span>private:</div><div><span style="white-space:pre-wrap">         </span>std::unordered_map<std::string, std::unique_ptr<llvm::MemoryBuffer>> CachedObjs;</div><div><br></div><div><span style="white-space:pre-wrap">    </span>public:</div><div><span style="white-space:pre-wrap">          </span>virtual void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj) {<span style="white-space:pre-wrap">           </span></div><div><span style="white-space:pre-wrap">                 </span>auto id = M->getModuleIdentifier();</div><div><span style="white-space:pre-wrap">                   </span>auto iter = CachedObjs.find(id);</div><div><span style="white-space:pre-wrap">                 </span>if (iter == CachedObjs.end()) {</div><div><span style="white-space:pre-wrap">                          </span>auto buf = llvm::MemoryBuffer::getMemBufferCopy(Obj.getBuffer(), Obj.getBufferIdentifier());</div><div><span style="white-space:pre-wrap">                             </span>CachedObjs.insert(std::make_pair(id, std::move(buf)));</div><div><span style="white-space:pre-wrap">                   </span>}</div><div><span style="white-space:pre-wrap">                </span>};</div><div><span style="white-space:pre-wrap">               </span></div><div><span style="white-space:pre-wrap">         </span>virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module *M) {</div><div><span style="white-space:pre-wrap">                     </span>auto id = M->getModuleIdentifier();</div><div><span style="white-space:pre-wrap">                   </span>auto iter = CachedObjs.find(id);</div><div><span style="white-space:pre-wrap">                 </span>if (iter != CachedObjs.end()) {</div><div><span style="white-space:pre-wrap">                          </span>llvm::MemoryBuffer& B = *iter->second;</div><div><span style="white-space:pre-wrap">                            </span>return llvm::MemoryBuffer::getMemBufferCopy(B.getBuffer(), B.getBufferIdentifier());</div><div><span style="white-space:pre-wrap">                     </span>}</div><div><span style="white-space:pre-wrap">                        </span>else</div><div><span style="white-space:pre-wrap">                             </span>return nullptr;</div><div><span style="white-space:pre-wrap">          </span>};</div><div><span style="white-space:pre-wrap">       </span>}</div></div><div><br></div><div>When I generate the code for the first time, everything works fine. the objects in CachedObjs are dumped to disk and reloaded for the next run. However with the next run (thus using the cached objects) the executionengine->getFunctionAddress() <b>sometimes </b>returns nullptr for a function that exists in the cache. I've traced into the cache call, and could see that my getObject() returned the right object. The object is loaded and no error was reported by ( MCJIT::generateCodeForModule(Module *M)):</div><div><br></div><div><div><div>  // Load the object into the dynamic linker.</div><div>  // MCJIT now owns the ObjectImage pointer (via its LoadedObjects list).</div><div>  ErrorOr<std::unique_ptr<object::ObjectFile>> LoadedObject =</div><div>    object::ObjectFile::createObjectFile(ObjectToLoad->getMemBufferRef());</div><div>  std::unique_ptr<RuntimeDyld::LoadedObjectInfo> L =</div><div>    Dyld.loadObject(*LoadedObject.get());</div><div><br></div><div>  if (Dyld.hasError())</div><div>    report_fatal_error(Dyld.getErrorString());</div></div></div><div><br></div><div><br></div><div>after the generateCodeForModule call, the findExistingSymbol is invoked. For some reason it cannot find my symbol. My symbol exists in the Module that was used as input for generateCodeForModule. It uses the object cache and that code was valid and generated in the previous run.</div><div><br></div><div>I tried to traced further in RuntimeDyld::SymbolInfo getSymbol()</div><div>and could see that the GlobalSymbolTable did not contained my symbol.</div><div><br></div><div>I obviously forgot something or did something wrong, what puzzeld me is that is quite semi-random. Even the most simple statements such as int x = 1; (no dependencies) sometime fails.</div><div><br></div><div>I did not hardcode any ptrs in the IR so the objects should be reusable over multiple instances.</div><div>Any one got a clue ?</div><div><br></div><div>Cheers,</div><div><br></div><div><br></div></div>
<br></div></div>_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>