Daniel Moya via llvm-dev
2018-Aug-27 17:37 UTC
[llvm-dev] Replacing a function from one module into another one
Hello LLVM Developers, I'm trying to replace a function defined in one module into another module (different files). The first issue I ran into was that llvm::Function does not have a method "moveBefore" or "moveAfter" as the llvm::BasicBlock or llvm::Instruction do, so I figured I would just move the BasicBlocks of the replacing function into the function that was being replaced, and then eliminate the original BasicBlocks. So far I had only one issue while eliminating the original BasicBlocks, I can only removeFromParent but not eraseFromParent, but the first function works fine anyways. For example, the original function is: define i32 @foo2(i32 %a, i32 %b) #0 { entry: %a.addr = alloca i32, align 4 %b.addr = alloca i32, align 4 store i32 %a, i32* %a.addr, align 4 store i32 %b, i32* %b.addr, align 4 And the function that is going to replace that is: define i32 @foo3(i32 %a, i32 %b) #0 { entry: %a.addr = alloca i32, align 4 %b.addr = alloca i32, align 4 store i32 %a, i32* %a.addr, align 4 store i32 %b, i32* %b.addr, align 4 So they are pretty much the same except for the name (the functions differ later in the code, but the error happens at the beginning). So what I do is move the entry block in foo3 before the entry block in foo2 and then "removeFromParent" the original entry block in the foo2. When I try to dump the Module, an error says: Use still stuck around after Def is destroyed: store i32 %0, i32* %a.addr1, align 4 Which I understand as that the new instruction "store" inserted in the new block in foo2 is still referring to the foo3 function's argument, which confused me at the beginning since I named both arguments the same to facilitate the process of substitution. What I thought as a solution was to then change the arguments of the function foo2 (the one that is being replaced) with the ones in the function foo3, to "move" the references, but I don't understand the difference between the functions of llvm::Function "addAttribute" and "addParamAttr", neither why they require to specify the attribute (or the Attribute::AttrKind <http://llvm.org/doxygen/classllvm_1_1Attribute.html#aab7ee4b8fd1d3e7e4cea87868855e60e> ) if the function already requires the argument position. When I did a similar process to change the calling instruction in the main function, I used the functions "setArgOperand" and "getArgOperand" which worked just fine, and also the "replaceAllUsesWith", I'm looking for something similar in the case of the function's arguments and their use in the function's body. So the question is: How can I properly replace a function (in my case only the function's body, since I'm limiting already that both functions have the same header) defined in one module intro another module. Regards, Daniel Moya -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180827/a56f8368/attachment.html>
Philip Pfaffe via llvm-dev
2018-Aug-28 16:04 UTC
[llvm-dev] Replacing a function from one module into another one
Hi Daniel, [CloneFunctionInto]( http://llvm.org/doxygen/namespacellvm.html#adea5a1faf61727d5a3c00684a22d8df6) helps you copy entire functions. It only takes care of the copy though, you'll have to empty out the replaced function manually. Cheers, Philip On Tue, Aug 28, 2018 at 5:53 PM Daniel Moya via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Hello LLVM Developers, > > I'm trying to replace a function defined in one module into another module > (different files). The first issue I ran into was that llvm::Function does > not have a method "moveBefore" or "moveAfter" as the llvm::BasicBlock or > llvm::Instruction do, so I figured I would just move the BasicBlocks of the > replacing function into the function that was being replaced, and then > eliminate the original BasicBlocks. So far I had only one issue while > eliminating the original BasicBlocks, I can only removeFromParent but not > eraseFromParent, but the first function works fine anyways. For example, > the original function is: > > define i32 @foo2(i32 %a, i32 %b) #0 { > entry: > %a.addr = alloca i32, align 4 > %b.addr = alloca i32, align 4 > store i32 %a, i32* %a.addr, align 4 > store i32 %b, i32* %b.addr, align 4 > > And the function that is going to replace that is: > > define i32 @foo3(i32 %a, i32 %b) #0 { > entry: > %a.addr = alloca i32, align 4 > %b.addr = alloca i32, align 4 > store i32 %a, i32* %a.addr, align 4 > store i32 %b, i32* %b.addr, align 4 > > So they are pretty much the same except for the name (the functions differ > later in the code, but the error happens at the beginning). So what I do is > move the entry block in foo3 before the entry block in foo2 and then > "removeFromParent" the original entry block in the foo2. When I try to dump > the Module, an error says: > > Use still stuck around after Def is destroyed: store i32 %0, i32* > %a.addr1, align 4 > > Which I understand as that the new instruction "store" inserted in the new > block in foo2 is still referring to the foo3 function's argument, which > confused me at the beginning since I named both arguments the same to > facilitate the process of substitution. What I thought as a solution was to > then change the arguments of the function foo2 (the one that is being > replaced) with the ones in the function foo3, to "move" the references, but > I don't understand the difference between the functions of llvm::Function > "addAttribute" and "addParamAttr", neither why they require to specify the > attribute (or the Attribute::AttrKind > <http://llvm.org/doxygen/classllvm_1_1Attribute.html#aab7ee4b8fd1d3e7e4cea87868855e60e> > ) if the function already requires the argument position. When I did a > similar process to change the calling instruction in the main function, I > used the functions "setArgOperand" and "getArgOperand" which worked just > fine, and also the "replaceAllUsesWith", I'm looking for something similar > in the case of the function's arguments and their use in the function's > body. > > So the question is: How can I properly replace a function (in my case only > the function's body, since I'm limiting already that both functions have > the same header) defined in one module intro another module. > > Regards, > Daniel Moya > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180828/a5222bd3/attachment.html>
Friedman, Eli via llvm-dev
2018-Aug-28 18:26 UTC
[llvm-dev] Replacing a function from one module into another one
On 8/27/2018 10:37 AM, Daniel Moya via llvm-dev wrote:> Hello LLVM Developers, > > I'm trying to replace a function defined in one module into another > module (different files). The first issue I ran into was that > llvm::Function does not have a method "moveBefore" or "moveAfter" as > the llvm::BasicBlock or llvm::Instruction do, so I figured I would > just move the BasicBlocks of the replacing function into the function > that was being replaced, and then eliminate the original BasicBlocks.Cross-module operations are tricky in general; I'd suggest using the Linker::linkModules API if possible. -Eli -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Daniel Moya via llvm-dev
2018-Sep-02 12:26 UTC
[llvm-dev] Replacing a function from one module into another one
Hello and thanks for the answer, I'm still facing issues, I'll do my best to explain my situation, as I explained, I have two modules, each one with its own main and functions, I would like to replace in the *oldModule* a function call that is calling *foo2* (defined in *oldModule*) to instead call *foo3*, which is defined in the *refModule. *So in summary, I have: 1. The original instruction call, defined in the main function of the oldModule, who is a calling function to foo2, I'll name it *oInst *(original Instruction) 2. The "new" instruction call, defined in the main function of the refModule, who is a calling function to foo3, I'll name it *nInst* (new Instruction) 3. The foo2 function definition, defined in the oldModule, I'll name it *oFunc *(original Function) 4. The foo3 function definition, defined in the refModule, I'll name it *nFunc* (new Function) 5. I have the parameters (or arguments?) of both functions, both in the calling instruction and in the function's definition, which I'll refer to as *p(oInst)*, *p(nInst)*, *p(oFunc)*, *p(nFunc) *(the parameters of) 6. For testing purposes, both foo2 and foo3 and defined identical, same returning type, parameter's type and even the same variable's name in the IR. So after calling the *llvm::LinkerlinkModules* function, I did: 1. First attempt: 1. llvm::CallInst *callOInst = static_cast<llvm::CallInst*>(oInst); // I cast the* oInst* to a llvm::CallInst 2. callOInst->setCalledFunction(nFunc); // now *oInst* should call nFunc Error: Call parameter type does not match function signature! %0 = load i32, i32* %a, align 4 i32 %call1 = call i32 @foo3(i32 %0, i32 %1) So even though the parameters are the same type, and defined identically in both modules, the *p(oInst)* apparently does not match the *p(nFunc)*. 2. Second attempt: 1. llvm::Instruction *nCloneInst = nInst->clone(); //Clone of the *nInst*, to avoid remove it from the refModule 2. nCloneInst->insertAfter(oInst); // I'll bring the nInst because I know *p(nInst)* and *p(nFunc)* match 3. nCloneInst->mutateType(oInst->getType()); //Idk why I have to this, but necessary for next line 4. oInst->replaceAllUsesWith(nCloneInst); 5. oInst->dropAllReferences(); 6. oInst->eraseFromParent(); Error: Instruction does not dominate all uses! %0 = load i32, i32* %a, align 4 %2 = call i32 @foo3(i32 %0, i32 %1) Great, now the *p(nInst)* are still referring to their definition in the refModule, so either I bring those instructions too (which sounds really messy) or somehow I change the *p(nInst)* to refer to the instructions in oldModule, which in my case are actually defined the same (but apparently the references don't change based on the name being the same in both modules). 3. Third attempt: 1. The same 1-4 steps as before, from cloning instruction to replaceAllUsesWith 2. llvm::CallInst *callNInst = static_cast<llvm::CallInst*>(nCloneInst); 3. llvm::CallInst *callOInst = static_cast<llvm::CallInst*>(oInst); // cast both *oInst* and *nInst* 4. for (unsigned int i = 0; i < callOInst->getNumArgOperands(); i++) { callNInst->setArgOperand(i,callOInst->getArgOperand(i)); } //replace *p(nInst)* with *p(oInst)* 5. The same 5-6 steps as before, drop and erase Error: Call parameter type does not match function signature! %0 = load i32, i32* %a, align 4 i32 %2 = call i32 @foo3(i32 %0, i32 %1) So back to the first problem, the *p(nInst) *(now converted to *p(oInst)*) apparently does not match the *p(nFunc)*. I also looked into the *CloneFunctionInto *function, but I didn't understand the arguments of it, and there's really no documentation or examples that I could find on the internet. Specifically, I have troubles with *llvm::SmallVectorImpl< llvm::ReturnInst *> &Returns *argument, I don't know how to initialize it, it doesn't have a 0 argument constructor and if I try: llvm::SmallVectorImpl< llvm::ReturnInst *> ReturnsArg llvm::SmallVectorImpl< llvm::ReturnInst *>(2); // Just as an example It says that constructor is protected. I didn't want to go further since I'm clueless on how to properly use this function, and I'm even not completely sure if it would fix all the troubles that I've been having with the other three attempts. Btw, all these errors happen when I try to run (through JIT) the module, a workaround that I know that I can do for all my attempts is just to dump the module to a file, and then reload it and execute it (I know it works since in both oldModule and refModule I use the same IR variable's names) but I would like to do the work the *right* way and not having to inefficiently dump a file just to reload it again and get all the references right. Thanks for the help in advance, I'll be really grateful for any advice or light in my situation. Regards, Daniel Moya El mar., 28 de ago. de 2018 a la(s) 20:26, Friedman, Eli ( efriedma at codeaurora.org) escribió:> On 8/27/2018 10:37 AM, Daniel Moya via llvm-dev wrote: > > Hello LLVM Developers, > > > > I'm trying to replace a function defined in one module into another > > module (different files). The first issue I ran into was that > > llvm::Function does not have a method "moveBefore" or "moveAfter" as > > the llvm::BasicBlock or llvm::Instruction do, so I figured I would > > just move the BasicBlocks of the replacing function into the function > > that was being replaced, and then eliminate the original BasicBlocks. > > Cross-module operations are tricky in general; I'd suggest using the > Linker::linkModules API if possible. > > -Eli > > -- > Employee of Qualcomm Innovation Center, Inc. > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux > Foundation Collaborative Project > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180902/24afc7fa/attachment.html>
Maybe Matching Threads
- Replacing a function from one module into another one
- Replacing a function from one module into another one
- Replacing a function from one module into another one
- Replacing a function from one module into another one
- Replacing a function from one module into another one