Value* as used by the non-JITted interpreter

Hi all,

I've now got my LLVM-based model checker more or less working, but I'm seeing something a bit strange happening.

As you may remember, I started with the lli code and extended it considerably. I have retained something that looks vaguely like the original ExecutionContext stack, though I now have one stack per thread, and the whole data structure is implemented with custom collection classes that support versioning and rollback. I use a hashmap (analogous to std::map semantically) to map Value* pointers onto GenericValue objects, as per the original code. This seems to work fine nearly all of the time, but occasionally I'm seeing the memory pointed to by the Value* objects go away, and lookups fail (probably due to the same mechanism). I have noticed that during execution, Instruction* pointers have a relatively short lifetime (e.g. I can't log them and play them back later, I have to dump them to text straight away and log the text instead), so presumably whatever it is that is causing the Value/Instruction objects to move around is also at root of the interpreter's approach of mapping Value*s to GenericValues.

I suspect I'm probably right in thinking that this was probably always a bug in the interpreted (non-JITted) version of lli, and that I've inherited the problem. What is it in the interpreter that causes Value objects to move around and/or cease to exist at run time? Is there any sensible workaround short of having to do some very nontrivial changes?

Thank you in advance,
Sarah Thompson

PS: Fridays seem to be a good day for showstoppers on my project for some reason!

I've now got my LLVM-based model checker more or less working, but I'm

Cool

seeing something a bit strange happening.

ok

objects, as per the original code. This seems to work fine nearly all of
the time, but occasionally I'm seeing the memory pointed to by the
Value* objects go away, and lookups fail (probably due to the same
mechanism). I have noticed that during execution, Instruction* pointers
have a relatively short lifetime (e.g. I can't log them and play them
back later, I have to dump them to text straight away and log the text
instead), so presumably whatever it is that is causing the
Value/Instruction objects to move around is also at root of the
interpreter's approach of mapping Value*s to GenericValues.

The only time that I'm aware of the interpreter changing the code is when it executes an intrinsic function. For example, when it executes llvm.popcnt.*, the first time the call is found, it is deleted and lowered to a sequence of instructions that implements the operation.

Are the vanishing instructions all calls to intinsics? If so, this could be the case. The thing that does this is this code in Execution.cpp:

       // If it is an unknown intrinsic function, use the intrinsic lowering
       // class to transform it into hopefully tasty LLVM code.
       //
       Instruction *Prev = CS.getInstruction()->getPrev();
       BasicBlock *Parent = CS.getInstruction()->getParent();
       IL->LowerIntrinsicCall(cast<CallInst>(CS.getInstruction()));

-Chris