[llvm-dev] function call replacement

John Criswell via llvm-dev llvm-dev at lists.llvm.org
Tue Jun 21 07:50:29 PDT 2016


On 6/21/16 3:10 AM, Pierre Gagelin wrote:
> Hi,
>
> Thanks both of you for the help. I just missed that Create function 
> had many optional arguments... sorry for that. However my problem 
> wasn't coming from here (IRBuilder CreateCall function still return a 
> pointer to CallInst so I just added 2 times the call?). I didn't 
> wanted to detail the all issue previously because I knew I had a 
> problem with my syntax. So here's my problem:
>
> I am doing this replacement operation in a FunctionPass (this is no 
> restriction, I could do it on a ModulePass if that's a solution). On 
> each Function given I do an iteration over the instructions and 
> replace (if it's a call to the right function) the call. It's like this:
>
> bool FDPFunction::runOnFunction(Function &F) {
>   bool res = false;
>   TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
>
>   for (inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) {
>     Instruction *I = &*i;
>
>     if (!I) {
>       errs() << "error: null pointer instruction\n";
>       break;
>     } else if (isMyFunctionCall(I, TLI)) {
>       errs() << "found a call to the function to replace\n";
>       res = true;
>       replacement_function(I);
>     } else {
>       errs() << "default: trash instruction\n";
>     }
>   }
>
>   return res;
> }
>
> The problem is that after the first replacement, the iterator becomes 
> a null pointer.

You might be invalidating the iterator after inserting the first 
CallInst.  There are multiple ways to solve this problem:

 1. Make your pass derive from the InstVistor class and implement a
    visitCallInst() method.  I believe the iterators in the InstVistor
    class do not get invalidated when new instructions are added.
 2. Iterate over all the instructions first and record the ones to
    replace in a container (e.g., a std::vector<>).  A second loop
    iterates over the container and replaces all the CallInsts stored
    therein.
 3. Look up the iterator invalidation rules for the instruction iterator
    and use the iterator in a way that does not invalidate the iterator.


Regards,

John Criswell


> With the break instruction the program is correctly instrumented for 
> the first call (about that: what is the use of replaceAllUsesWith 
> function? I thought it would replace all uses of the function... but 
> just one is done). I can then link it and execute with lli (I still 
> get a: "*** Error in `lli': corrupted double-linked list: 0xaddress 
> ***" but after the whole execution is done).
>
> But if I remove the break and the if condition associated, well I get 
> a null pointer exception : Assertion `Val && "isa<> used on a null 
> pointer"' failed
>
> I tried to clone the current instruction to not modify the iterator 
> but the ReplaceInstWithInst will cause troubles (probably because a 
> copied instruction has no parents):
>
> #0 0x0000000002a95b5c llvm::sys::PrintStackTrace(llvm::raw_ostream&) 
> /home/pierre/Desktop/llvm/lib/Support/Unix/Signals.inc:400:0
> #1 0x0000000002a95edf PrintStaI tried to clone the current instruction 
> to not modify the iterator but the ReplaceInstWithInst will cause 
> troublesckTraceSignalHandler(void*) 
> /home/pierre/Desktop/llvm/lib/Support/Unix/Signals.inc:468:0
> #2 0x0000000002a94145 llvm::sys::RunSignalHandlers() 
> /home/pierre/Desktop/llvm/lib/Support/Signals.cpp:44:0
> #3 0x0000000002a953a8 SignalHandler(int) 
> /home/pierre/Desktop/llvm/lib/Support/Unix/Signals.inc:254:0
> #4 0x00007fe358d3dd10 __restore_rt 
> (/lib/x86_64-linux-gnu/libpthread.so.0+0x10d10)
> #5 0x00000000011fe489 llvm::iplist<llvm::Instruction, 
> llvm::SymbolTableListTraits<llvm::Instruction> 
> >::insert(llvm::ilist_iterator<llvm::Instruction>, llvm::Instruction*) 
> /home/pierre/Desktop/llvm/include/llvm/ADT/ilist.h:415:0
> #6 0x0000000002abc20d llvm::ReI tried to clone the current instruction 
> to not modify the iterator but the ReplaceInstWithInst will cause 
> troublesplaceInstWithInst(llvm::SymbolTableList<llvm::Instruction>&, 
> llvm::ilist_iterator<llvm::Instruction>&, llvm::Instruction*) 
> /home/pierre/Desktop/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp:198:0
> #7 0x0000000002abc2a5 llvm::ReplaceInstWithInst(llvm::Instruction*, 
> llvm::Instruction*) 
> /home/pierre/Desktop/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp:210:0
>
> Any idea on what could be the cause of the null pointer and how to 
> avoid it?
>
> Thanks a lot for your time!
> Pierre
>
>
> On 20 June 2016 at 15:45, John Criswell <jtcriswel at gmail.com 
> <mailto:jtcriswel at gmail.com>> wrote:
>
>     On 6/20/16 6:17 AM, Pierre Gagelin via llvm-dev wrote:
>>     Hi everyone,
>>
>>     I am trying to replace the call of a certain function with a call
>>     to another function. It would for example replace the following:
>>
>>     %call = tail call noalias i8* @func(i64 10)
>>     by
>>     %call = tail call noalias i8* @other_func(i64 10)
>>
>>     I managed to declare other_func correctly but I am having
>>     troubles to understand how I should proceed to do the replacement.
>>
>>     I tried to use ReplaceInstWithInst function as follows:
>>
>>     CallInst *call_to_other_func_inst =
>>     IRBuilder.CreateCall(ptr_to_other_func, args);
>>     ReplaceInstWithInst(call_to_func_inst, newI);
>>
>>     LLVM builds correctly but the instrumentation crashes at
>>     optimization time. I know this isn't the correct way to do it
>>     because IRBuilder generates IR and I just want to have an
>>     instance of a CallInst. But I don't see how it is supposed to be
>>     done?
>
>     Do you have assertions enabled?  If so, is the crash an assertion
>     failure and, if so, which assertion is failing?  It's nearly
>     impossible to tell what the problem is just by knowing that it is
>     crashing.
>
>>
>>     There are methods to create CallInst in the Instruction.h file
>>     but those needs to give an inserting point. Shoud I insert the
>>     call to other_func before the one to func and just remove the
>>     call instruction to func?
>
>     Yes.  You need to place the new call instruction within the same
>     basic block as the old call instruction. Placing it right before
>     the old call instruction is a good place.
>
>     The code that Ashutosh provided is what I'd use to do what you're
>     doing.
>
>     Regards,
>
>     John Criswell
>
>>
>>     Thanks for your help,
>>     Pierre
>>
>>
>>     _______________________________________________
>>     LLVM Developers mailing list
>>     llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
>>     http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>
>     -- 
>     John Criswell
>     Assistant Professor
>     Department of Computer Science, University of Rochester
>     http://www.cs.rochester.edu/u/criswell
>
>


-- 
John Criswell
Assistant Professor
Department of Computer Science, University of Rochester
http://www.cs.rochester.edu/u/criswell

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160621/e3ed6c3e/attachment.html>


More information about the llvm-dev mailing list