[LLVMdev] Wrong behavior modifying and executing llvm::Function with JIT Engine

Adrian Ortega elfus0.1 at gmail.com
Sun Jun 29 07:53:43 PDT 2014


Another thing I just tried was to give 'sum()' the following implementation:

     int sum(int a, int b) { return 99; }

Now what I did was:

     1. Call 'get_int()' which will call 'sum(){return 99;}'
     2. Change the call instruction to 'sum_mockup', I dumped the code 
and the change is done, but when calling 'get_int()' it calls 
'sum(){return 99;}'

I know it might be too rushed to say what the problem is, but it seems 
that when a function has been compiled and executed in the JIT engine, 
it will remain linked to other functions no matter what regardless of 
changing the call instruction.

On 29/06/14 09:00, Adrian Ortega wrote:
> I tried using 'getPointerToFunction()' and the correct function I 
> generated was called from C code, but when it runs inside the JIT 
> engine it always returns the value of the first function. I even tried 
> to 'deleteBody()' and 'removeFromParent()' from the first function 
> generated, and still returns the first value.
>
> I also tried using 'dump()' to see if the values where being updated. 
> This is the C code I run with the JIT engine:
>
>     #include <stdio.h>
>
>     int sum(int a, int b); // declaration
>
>     int get_int(int a, int b)
>     {
>         int x = sum(a,b);
>         printf("The result was: %d\n",x);
>         return x;
>     }
>
> As you can see I print the return value of the function. The functions 
> I generate and that I called 'get_int_*()' in the previous email are 
> now called 'sum_mockup_N()'. This is the code LLVM IR code:
>
>     ; Function Attrs: nounwind uwtable
>     define i32 @get_int(i32 %a, i32 %b) #0 {
>     entry:
>       %a.addr = alloca i32, align 4
>       %b.addr = alloca i32, align 4
>       %x = alloca i32, align 4
>       store i32 %a, i32* %a.addr, align 4
>       store i32 %b, i32* %b.addr, align 4
>       %0 = load i32* %a.addr, align 4
>       %1 = load i32* %b.addr, align 4
>     *%call = call i32 @sum_mockup(i32 %0, i32 %1)* *; Use the first
>     function generated*
>       store i32 %call, i32* %x, align 4
>       %2 = load i32* %x, align 4
>       %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
>     ([20 x i8]* @.str, i32 0, i32 0), i32 %2)
>       %3 = load i32* %x, align 4
>       ret i32 %3
>     }
>
>     The result was: 10
>
>     ; sum always remains a declaration
>     declare i32 @sum(i32, i32) #1
>
>     *define i32 @sum_mockup(i32, i32)* *#1 {**
>     **mockup_block:**
>     **ret i32 10**
>     **}*
>
>     ****************************
>     *[C Code] getPointerToFunction()= 10****// Pointer to*
>     *@sum_mockup(i32, i32)*
>     ****************************
>
>     ; Function Attrs: nounwind uwtable
>     define i32 @get_int(i32 %a, i32 %b) #0 {
>     entry:
>       %a.addr = alloca i32, align 4
>       %b.addr = alloca i32, align 4
>       %x = alloca i32, align 4
>       store i32 %a, i32* %a.addr, align 4
>       store i32 %b, i32* %b.addr, align 4
>       %0 = load i32* %a.addr, align 4
>       %1 = load i32* %b.addr, align 4
>     *%call = call i32 @sum(i32 %0, i32 %1)* *// Change it back to the
>     declaration*
>       store i32 %call, i32* %x, align 4
>       %2 = load i32* %x, align 4
>       %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
>     ([20 x i8]* @.str, i32 0, i32 0), i32 %2)
>       %3 = load i32* %x, align 4
>       ret i32 %3
>     }
>
>
>     ; Function Attrs: nounwind uwtable
>     define i32 @get_int(i32 %a, i32 %b) #0 {
>     entry:
>       %a.addr = alloca i32, align 4
>       %b.addr = alloca i32, align 4
>       %x = alloca i32, align 4
>       store i32 %a, i32* %a.addr, align 4
>       store i32 %b, i32* %b.addr, align 4
>       %0 = load i32* %a.addr, align 4
>       %1 = load i32* %b.addr, align 4
>     *%call = call i32 @sum_mockup_1(i32 %0, i32 %1) ; Use the other
>     function generated*
>       store i32 %call, i32* %x, align 4
>       %2 = load i32* %x, align 4
>       %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
>     ([20 x i8]* @.str, i32 0, i32 0), i32 %2)
>       %3 = load i32* %x, align 4
>       ret i32 %3
>     }
>
>     The result was: 10
>
>     declare i32 @sum(i32, i32) #1
>
>
>     *define i32 @sum_mockup_1(i32, i32) #1 {**
>     **mockup_block:**
>     **ret i32 5**
>     **}*
>
>     ****************************
>     *[C Code] getPointerToFunction()= 5* *// Pointer to*
>     *@sum_mockup_1(i32, i32)*
>     ****************************
>
>     ; Function Attrs: nounwind uwtable
>     define i32 @get_int(i32 %a, i32 %b) #0 {
>     entry:
>       %a.addr = alloca i32, align 4
>       %b.addr = alloca i32, align 4
>       %x = alloca i32, align 4
>       store i32 %a, i32* %a.addr, align 4
>       store i32 %b, i32* %b.addr, align 4
>       %0 = load i32* %a.addr, align 4
>       %1 = load i32* %b.addr, align 4
>     *%call = call i32 @sum(i32 %0, i32 %1)* *// Change it back to the
>     declaration*
>       store i32 %call, i32* %x, align 4
>       %2 = load i32* %x, align 4
>       %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
>     ([20 x i8]* @.str, i32 0, i32 0), i32 %2)
>       %3 = load i32* %x, align 4
>       ret i32 %3
>     }
>
>
> If I get a pointer to the function 'get_int()' I still have the same 
> problem of getting the same return value of the first generated 
> function. But when I get a pointer to the generated functions 
> themselves 'sum_mockup_*()' I get the actual value I'm expecting.
>
>
>
> On 28/06/14 22:48, Yaron Keren wrote:
>> getFunction() -> getPointerToFunction()
>>
>>
>>
>>
>> 2014-06-29 6:40 GMT+03:00 Yaron Keren <yaron.keren at gmail.com 
>> <mailto:yaron.keren at gmail.com>>:
>>
>>     Hi Adrian,
>>
>>     freeMachineCodeForFunction is required but
>>     recompileAndLinkFunction is not,
>>     you can use getFunction() always.
>>
>>     Try to  M->dump() calling M->getFunction() where M is the Module *.
>>     See if how the changes appear in the module dump as expected.
>>
>>     Yaron
>>
>>
>>
>>
>>
>>     2014-06-29 5:56 GMT+03:00 Adrian Ortega <elfus0.1 at gmail.com
>>     <mailto:elfus0.1 at gmail.com>>:
>>
>>         Hello,
>>
>>         The problem I'm having is that I modify a function body by
>>         using 'Value::replaceAllUsesWith' and then execute it with
>>         the JIT engine several times but I always get the output from
>>         the first iteration for all the iterations.
>>
>>         This is what I do:
>>
>>
>>         I generate the following 2 functions on the fly based on the
>>         FunctionType of the declaration below in C code.
>>
>>             define i32 @get_int_5(i32, i32) #1 {
>>               ret i32 5
>>             }
>>
>>             define i32 @get_int_10(i32, i32) #1 {
>>               ret i32 10
>>             }
>>
>>         I have the following C code:
>>
>>
>>             // This is only a declaration
>>             // I use this FunctionType to generate the functions above
>>             int sum(int a, int b);
>>
>>             int get_int()
>>             {
>>                 return sum(a,b);
>>             }
>>
>>         I replace the  call to 'sum()' by calling
>>         Value::replaceAllUsesWith for one of the functions generated
>>         above, run with JIT. I checked the code generated and it
>>         actually changes the call from 'sum()' to 'get_int_5()' and I
>>         get a 5 as return value when I call the function with the JIT
>>         execution engine.
>>
>>         Then I repeat the previous step using
>>         'Value::replaceAllUsesWith' for the next function I generated
>>         and run it with JIT. Then again the code generated is what I
>>         expected, this time
>>         function call changes from 'sum()' to 'get_int_10()', however
>>         the problem is I get a 5 instead of a 10.
>>
>>         I tried 'recompileAndLinkFunction' as well as
>>         'freeMachineCodeForFunction' and I always get the return
>>         value from the first function, and not the second as I should
>>         even though the generated code that I dump() says that it has
>>         the correct function call.
>>
>>         I am using version 3.4 for both clang and llvm. And also I'm
>>         using the JIT Engine and not the MCJIT.
>>
>>         Do you have have any idea why the references or 'uses'
>>         changes are not reflected in the code JIT'ed ?
>>
>>         Regards.
>>
>>
>>
>>
>>
>>
>>
>>
>>         _______________________________________________
>>         LLVM Developers mailing list
>>         LLVMdev at cs.uiuc.edu <mailto:LLVMdev at cs.uiuc.edu>
>>         http://llvm.cs.uiuc.edu
>>         http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>>
>>
>

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


More information about the llvm-dev mailing list