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

Philip Pfaffe via llvm-dev llvm-dev at lists.llvm.org
Wed Sep 5 02:15:33 PDT 2018


Hi Daniel,

the implementation of [CloneModule](
http://llvm.org/doxygen/CloneModule_8cpp_source.html) should be a good
example. Generally all you need to do in your case is map old arguments to
new arguments.

Cheers,
Philip

On Tue, Sep 4, 2018 at 1:18 PM Daniel Moya <danielmscr1994 at gmail.com> wrote:

> Hi Philip,
>
> Thank you very much for your answer, the vector declaration example
> worked. I'm pretty sure the ValueToValueMapTy is the last thing I need
> because I even saw there is another function that could help me llvm*:*
> :RemapFunction
> <http://llvm.org/doxygen/namespacellvm.html#addf0183e92893bdbcde00fc9091dda93>;
> but my problem is that I don't know how to populate the ValueToValueMapTy
> (VMap) and I couldn't find a single complete example on the internet. To
> begin with, as the name implies (and also from some errors that I got) the
> ValueToValueMapTy takes a std::pair<llvm::Value, llvm::Value>, but what I
> need is to map the arguments (llvm::Attribute) of both functions (the first
> argument of foo2 is equivalent to the first argument of foo3, and so on),
> however, apparently there's no transformation from a llvm::Attribute to a
> llvm::Value. I'm using the function getAttribute
> <http://llvm.org/doxygen/classllvm_1_1Function.html#ab2a5fc8baaee7e74dbe47d848508745a>
>  (unsigned <http://llvm.org/doxygen/classunsigned.html> i, StringRef
> <http://llvm.org/doxygen/classllvm_1_1StringRef.html> Kind
> <http://llvm.org/doxygen/ARMAsmParser_8cpp.html#a5ec5335889cd241b0ccfd4e4e58cf52e>
> ) const
> <http://llvm.org/doxygen/AArch64PromoteConstant_8cpp.html#a90f8350fecae261c25be85d38b451bff> to
> get the attributes, but I don't even understand why is it required to give
> the StringRef <http://llvm.org/doxygen/classllvm_1_1StringRef.html> Kind
> <http://llvm.org/doxygen/ARMAsmParser_8cpp.html#a5ec5335889cd241b0ccfd4e4e58cf52e> if
> what I need is just the attribute of the function in the *i *position.
> I'm really thankful for the quick responses and for the attention received.
>
> Regards,
> Daniel Moya
>
>
>
>
>
> El lun., 3 de sep. de 2018 a la(s) 18:42, Philip Pfaffe (
> philip.pfaffe at gmail.com) escribió:
>
>> 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/20180905/00796176/attachment.html>


More information about the llvm-dev mailing list