Call external (non-JIT) function from JIT

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;
}

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

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 ; [#uses=1]
%call = call i32 @known(i32 %tmp) ; [#uses=1]
store i32 %call, i32* %i
%tmp1 = load i32* %i ; [#uses=1]
%call2 = call i32 (i8*, …)* @printf(i8* getelementptr inbounds ([16 x i8]* @.str, i32 0, i32 0), i32 %tmp1) ; [#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 :slight_smile:

-Frank

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