Call external (non-JIT) function from JIT

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Call external (non-JIT) function from JIT

Frank Fuchs
Hi I'm rather new to llvm+clang,
but i'm intrigued by the idea to create some jit "scripting" extension for arbitrary c++ applications
using llvm and clang (the scripts shall use c or even c++ syntax).
I started looking into the clang-interpreter example which in my eyes is already half way there.
Now I tried to extend the functionality of the example by adding a mapping for an already defined
C-function to the JIT. ... Strangely enough the code did compile afterwards, but of course it didn't work.

Here is what I did:

examples/clang-interpreter/main.cpp
int Execute(llvm::Module *Mod, char * const *envp)
{
.....
  llvm::Function *EntryFn = Mod->getFunction("main");
  // external function
  llvm::Function *KnownFunction = llvm::Function::Create(llvm::TypeBuilder<int(int), false>::get(Mod->getContext()),llvm::GlobalValue::ExternalLinkage, "known", Mod);
  EE->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne);

  if (!EntryFn)
....
}

my_test.cpp:
#include <stdio.h>
int main()
{
        int i=1;
        i=known(i);
        printf("Ext. CALL %d \n\n",i);
        return 0;
}

tests> clang-interpreter -v my_test.cpp

Here's the error message:
main.cpp:5:4: error: use of undeclared identifier 'known'
        i=known(i);
          ^
1 error generated.

also defining "known" as: extern "C" int known(int);    does not solve the issue, the error is then:
LLVM ERROR: Program used external function 'known' which could not be resolved!


Obviously something else needs to be done in order to resolve the function., but I don't know what.
So any help is appreciated!

Thank you in advance
Frank
 




_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Call external (non-JIT) function from JIT

Eli Friedman
On Tue, Jul 13, 2010 at 12:46 PM, Frank Fuchs <[hidden email]> wrote:
> Here's the error message:
> main.cpp:5:4: error: use of undeclared identifier 'known'
>        i=known(i);
>          ^
> 1 error generated.

Right... the frontend has no clue what mapping you're doing in the backend.

> also defining "known" as: extern "C" int known(int);    does not solve the issue, the error is then:
> LLVM ERROR: Program used external function 'known' which could not be resolved!

I have a feeling you're not actually adding a mapping for "known"; try
dumping the module.

-Eli

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Call external (non-JIT) function from JIT

Frank Fuchs
On Tue, Jul 13, 2010 at 12:46 PM, Frank Fuchs <[hidden email]> wrote:
Here's the error message:
main.cpp:5:4: error: use of undeclared identifier 'known'
      i=known(i);
        ^
1 error generated.

Right... the frontend has no clue what mapping you're doing in the backend.

also defining "known" as: extern "C" int known(int);    does not solve the issue, the error is then:
LLVM ERROR: Program used external function 'known' which could not be resolved!

I have a feeling you're not actually adding a mapping for "known"; try
dumping the module.

-Eli

Ok here is the output of Mod->dump() called right before runAsFunctionMain(...). I am referring to the example with the extern "C" int known(int) declaration!  

; ModuleID = 'test.cpp'
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
target triple = "x86_64-apple-darwin10.0.0"

@.str = private constant [16 x i8] c"Ext. CALL %d \0A\0A\00" ; <[16 x i8]*> [#uses=1]

define i32 @main() ssp {
entry:
 %retval = alloca i32, align 4                   ; <i32*> [#uses=1]
 %i = alloca i32, align 4                        ; <i32*> [#uses=4]
 store i32 0, i32* %retval
 store i32 1, i32* %i
 %tmp = load i32* %i                             ; <i32> [#uses=1]
 %call = call i32 @known(i32 %tmp)               ; <i32> [#uses=1]
 store i32 %call, i32* %i
 %tmp1 = load i32* %i                            ; <i32> [#uses=1]
 %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str, i32 0, i32 0), i32 %tmp1) ; <i32> [#uses=0]
 ret i32 0
}

declare i32 @known(i32)

declare i32 @printf(i8*, ...)

declare i32 @known1(i32)


I'm not sure how to interpret this ... but the "known1" seems to be the mapped function, while "known" is the extern "C" declared one (checked that by renaming "known" in test.cpp). ... End of knowledge :)

-Frank
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Call external (non-JIT) function from JIT

Eli Friedman
On Tue, Jul 13, 2010 at 1:56 PM, Frank Fuchs <[hidden email]> wrote:
> I'm not sure how to interpret this ... but the "known1" seems to be the
> mapped function, while "known" is the extern "C" declared one (checked that
> by renaming "known" in test.cpp). ... End of knowledge :)

Right... I think using getOrInsertFunction instead of
llvm::Function::Create will solve the issue.  If you use
llvm::Function::Create with an already existing name, it will
automatically rename it to avoid the conflict; this is nice when you
don't care about the name, but not what you want here.

-Eli
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Call external (non-JIT) function from JIT

Frank Fuchs
> On Tue, Jul 13, 2010 at 1:56 PM, Frank Fuchs <[hidden email]> wrote:
>> I'm not sure how to interpret this ... but the "known1" seems to be the
>> mapped function, while "known" is the extern "C" declared one (checked that
>> by renaming "known" in test.cpp). ... End of knowledge :)
>
> Right... I think using getOrInsertFunction instead of
> llvm::Function::Create will solve the issue.  If you use
> llvm::Function::Create with an already existing name, it will
> automatically rename it to avoid the conflict; this is nice when you
> don't care about the name, but not what you want here.
>
> -Eli


Great! It works ... thank you!
Just for the record, I replaced the Function::create call by this one:

llvm::Function *KnownFunction = cast<llvm::Function>(Mod->getOrInsertFunction("known",llvm::TypeBuilder<int(int), false>::get(Mod->getContext())));

So this would be the way to declare C Functions to the "Script" ... now can this be done for C++ methods as well?
Is there a possibility that the JIT "links" against C++ classes from the "host" application?

-Frank
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev