[llvm-dev] Replacing a function from one module into another one

Ahmad Nouralizadeh Khorrami via llvm-dev llvm-dev at lists.llvm.org
Sun Sep 2 08:00:11 PDT 2018


Hi.
Besides the LLVM linker, you can also use this tool:
https://github.com/travitch/whole-program-llvm
It links all the modules and produces a single module containing every
function.
Regards.

On Sun, 2 Sep 2018 at 16:57, Daniel Moya via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> 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
>>
>> _______________________________________________
> 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/20180902/b4c763ca/attachment.html>


More information about the llvm-dev mailing list