cyclical dependence between caller and callee in JIT

The common idiom to delete any Value* is:

V->replaceAllUsesWith(UndefValue::get(V->getType());
V->eraseFromParent();

Does that work for functions? You may need to make sure the 'undef' has a
pointer to function type instead of the function type.

I tried this code sample, passing the type returned by
llvm::Function::getType(), but i get this assertion failure:

  %"calling function" = call i32 @X.foo(i32 %read)
F is used in instruction:
  %"calling function" = call i32 @X.foo(i32 %read)
mytests: /home/charlesq/third_party/llvm-3.1.src/include/llvm/ADT/ValueMap.h:220:
void llvm::ValueMapCallbackVH<KeyT, ValueT,

::allUsesReplacedWith(llvm::Value*) [with KeyT = const

llvm::Function*; ValueT = {anonymous}::JITEmitter::EmittedCode; Config
= {anonymous}::JITEmitter::EmittedFunctionConfig]: Assertion
`isa<KeySansPointerT>(new_key) && "Invalid RAUW on key of ValueMap<>"'
failed.

Apparently, the undefValue is expected to be isa<KeySansPointerT>. Are
there any examples or references about how to bring such an
undefValue?

charles quarra wrote:

The common idiom to delete any Value* is:

V->replaceAllUsesWith(UndefValue::get(V->getType());
V->eraseFromParent();

Does that work for functions? You may need to make sure the 'undef' has a
pointer to function type instead of the function type.

I tried this code sample, passing the type returned by
llvm::Function::getType(), but i get this assertion failure:

   %"calling function" = call i32 @X.foo(i32 %read)
F is used in instruction:
   %"calling function" = call i32 @X.foo(i32 %read)
mytests: /home/charlesq/third_party/llvm-3.1.src/include/llvm/ADT/ValueMap.h:220:
void llvm::ValueMapCallbackVH<KeyT, ValueT,
>::allUsesReplacedWith(llvm::Value*) [with KeyT = const
llvm::Function*; ValueT = {anonymous}::JITEmitter::EmittedCode; Config
= {anonymous}::JITEmitter::EmittedFunctionConfig]: Assertion
`isa<KeySansPointerT>(new_key)&& "Invalid RAUW on key of ValueMap<>"'
failed.

Apparently, the undefValue is expected to be isa<KeySansPointerT>. Are
there any examples or references about how to bring such an
undefValue?

Something else is going on. The problem isn't with your call to replaceAllUsesWith per se, the problem is that somebody (I would guess the JIT?) is holding it in a ValueMap.

We used to have a problem that some parts of the code would keep a mapping like so:
   std::map<Value *, ...>
while somebody else would modify the Value* without them noticing, leading to a dangling pointer in the map. To fix that, we invented the ValueMap which puts a Use that doesn't show up in the use_iterator on the Value it holds. When the Value is erased or RAUW'd, the ValueMap is notified and in this case decides that's not okay and terminates the program.

Probably what's happened here is that the calling function has had its code generated by the JIT, but not the callee. Thus the JIT emitted a call to a generated stub, and will do the codegen of the callee once that stub is reached. Of course, once the JIT is in this state, it holds on to the Function with a ValueMap in order to prevent things from getting out of sync.

Nick