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

Adrian Ortega elfus0.1 at gmail.com
Sun Jun 29 07:00:55 PDT 2014


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/3d16165f/attachment.html>


More information about the llvm-dev mailing list