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

Philip Pfaffe via llvm-dev llvm-dev at lists.llvm.org
Mon Sep 3 09:41:58 PDT 2018


Hi Daniel,

CloneFunctionInto wants to tell you about the new ReturnInstructions it
produced, you're expected to pass a vector for this purpose. You're free to
ignore these values, though, but you still have to pass that
vector:  SmallVector<ReturnInst*, 8> Returns;

For the argument remapping, you're supposed to pre-populate the VMap you
pass with the appropriate argument-to-argument mapping.

It's perfectly fine to use CloneFunctionInto across modules, btw. Only
operations across LLVMContexts are tricky.

Cheers,
Philip

On Mon, Sep 3, 2018 at 6:31 PM Daniel Moya via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> Thank you Ahmad,
>
> I figured out that, although the type of both p(oInst) and p(nInst) were
> the same, I had to:
>
> for (unsigned int i = 0; i < callOInst->getNumArgOperands(); i++) {
> callOInst->getArgOperand(i)->mutateType(callNInst->getArgOperand(i)->getType());
> }
>
> that solves the issue at the calling instruction in the main function, but
> now I see that *linkModules* does not work for me (it's a mess to bring
> all the other unnecessary functions from the reference module) so what I
> need is to directly move one function from one module to another one. I'm
> still facing the issue with the *llvm::SmallVectorImpl< llvm::ReturnInst
> *> &Returns *argument for the *CloneFunctionInto, *can anyone please give
> an example of use of that function? I guess that's the only way because
> otherwise if I move the blocks from foo3 in the refModule to the oldModule,
> the references of the moved block still point to the arguments of foo3
> defined in the refModule, and I don't know how to go instruction by
> instruction in all the moved blocks and correct the reference to point to
> the arguments in the oldModule's new function, this also sounds very messy
> and complicated.
>
>
> Regards,
> Daniel Moya
>
>
>
>
> El dom., 2 de sep. de 2018 a la(s) 23:18, Ahmad Nouralizadeh Khorrami (
> ahmad.llvm at gmail.com) escribió:
>
>> Hi Daniel,
>> The answer was for your first thread. The benefits are outlined in the
>> repository, but your problem is still there. I'm not sure. But this looks
>> similar to my recent problem. I think that a bitcast will solve the
>> problem. The types after the linking process may have different names but
>> the same contents. The links to the answers are as follows:
>> http://lists.llvm.org/pipermail/llvm-dev/2018-August/125413.html
>>
>> https://stackoverflow.com/questions/51894129/convert-function-pointer-call-to-function-call-at-the-ir-level
>> Regards.
>>
>> On Sun, 2 Sep 2018 at 23:30, Daniel Moya <danielmscr1994 at gmail.com>
>> wrote:
>>
>>> Hi Ahmad,
>>>
>>> What does that tool does besides what LLVM linker already does? I don't
>>> think my problem is in linking both modules, I think LLVM linker does the
>>> job for me, the issue is when changing the called function to call another
>>> function (in the example previously provided, to change it from foo2 to
>>> foo3, and adjusting the function parameter's references).
>>>
>>> Regards,
>>> Daniel Moya
>>>
>>> El dom., 2 de sep. de 2018 a la(s) 17:00, Ahmad Nouralizadeh Khorrami (
>>> ahmad.llvm at gmail.com) escribió:
>>>
>>>> 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
>>>>>
>>>> _______________________________________________
> 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/20180903/573153b9/attachment.html>


More information about the llvm-dev mailing list