Hello, I got very interested in LLVM project, and I decided to start writing my own scripting language based on it. By studying the documentation, I could not find how to call external function, written in C. That is, I have a set of functions written in C/C++, I generate code, using LLVM C++ interface, how can I call(or register in machine in run-time) my external functions? Maybe I just missed something. Please, give in which direction to search. Thanks in advance, look forward to your reply!
On Aug 19, 2008, at 13:36, kirill havok wrote:> I got very interested in LLVM project, and I decided to start > writing my own scripting language based on it. By studying the > documentation, I could not find how to call external function, > written in C. That is, I have a set of functions written in C/C++, I > generate code, using LLVM C++ interface, how can I call(or register > in machine in run-time) my external functions? Maybe I just missed > something. Please, give in which direction to search.Hi Kirill, Since LLVM goes to the bare metal, there is no need for an "FFI" or bindings to call native code. Simply create a declaration for the function—a Function with no body—and call it as any other function in your program. (Also, of course, link with a library to define the symbols.) It might be instructive to examine the llvm-gcc -S -emit- llvm output of a program like this: int MyExternalFn(int, int, int); int main(int, const char**, const char**) { return MyExternalFn(1, 2, 3); } Where you tweak MyExternalFn to have the desired prototype. To create a function declaration: From C++, simply call Function::Create and then do not add any basic blocks. From LLVM assembly, use the keyword "declare" instead of "define": http://llvm.org/docs/LangRef.html#functionstructure If you're using the JIT, you'll need to do the above, but also may need to register your functions using ExecutionEngine::addGlobalMapping. http://llvm.org/doxygen/classllvm_1_1ExecutionEngine.html#a8 Note that the C calling convention do not map directly to LLVM IR for many cases, so it's best to stick to simple parameter types (pointers and ints, for example) and also to verify that the LLVM FunctionTypes you use are correct on each platform you support. Good luck! — Gordon -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080819/8819edec/attachment.html>
Hi Gordon, I wrote a small example, but while running I get an error("Tied to execute an unknown external function"), where I am wrong? Thanks in advance. Kirill. int some_test_func( int ){ std::cout << "!!!!" << std::endl; return 8848; } int _tmain(int argc, _TCHAR* argv[]){ Module *M = new Module("test"); ExistingModuleProvider* MP = new ExistingModuleProvider(M); ExecutionEngine* EE = ExecutionEngine::create(MP, false); std::vector<const Type *> func_args; func_args.push_back(Type::Int32Ty); FunctionType * func_type = FunctionType::get(Type::Int32Ty, func_args, false); Function * my_function = Function::Create( func_type, Function::ExternalLinkage, "some_test_func", M ); EE->addGlobalMapping( my_function, (void*)&some_test_func ); Function *FooF = cast<Function>(M->getOrInsertFunction("foo", Type::Int32Ty, (Type *)0)); BasicBlock * BB = BasicBlock::Create("EntryBlock", FooF); Value *Ten = ConstantInt::get(Type::Int32Ty, 10); CallInst *Add1CallRes = CallInst::Create(my_function, Ten, "some_test_func", BB); Add1CallRes->setTailCall(true); ReturnInst::Create(Add1CallRes, BB); std::cout << "We just constructed this LLVM module:\n\n" << *M; std::cout << "\n\nRunning foo: " << std::flush; std::vector<GenericValue> noargs; GenericValue gv = EE->runFunction(FooF, noargs); std::cout << "Result: " << gv.IntVal.toStringUnsigned(10) << "\n"; return 0; } 2008/8/19, Gordon Henriksen <gordonhenriksen at me.com>:> > On Aug 19, 2008, at 13:36, kirill havok wrote: > > I got very interested in LLVM project, and I decided to start writing my own > scripting language based on it. By studying the documentation, I could not > find how to call external function, written in C. That is, I have a set of > functions written in C/C++, I generate code, using LLVM C++ interface, how > can I call(or register in machine in run-time) my external functions? Maybe > I just missed something. Please, give in which direction to search. > > Hi Kirill, > > Since LLVM goes to the bare metal, there is no need for an "FFI" or bindings > to call native code. Simply create a declaration for the function—a Function > with no body—and call it as any other function in your program. (Also, of > course, link with a library to define the symbols.) It might be instructive > to examine the llvm-gcc -S -emit-llvm output of a program like this: > > int MyExternalFn(int, int, int); > > int main(int, const char**, const char**) { > return MyExternalFn(1, 2, 3); > } > > > Where you tweak MyExternalFn to have the desired prototype. > > To create a function declaration: > > > From C++, simply call Function::Create and then do not add any basic blocks. > From LLVM assembly, use the keyword "declare" instead of "define": > http://llvm.org/docs/LangRef.html#functionstructure > > > If you're using the JIT, you'll need to do the above, but also may need to > register your functions using > ExecutionEngine::addGlobalMapping. > > http://llvm.org/doxygen/classllvm_1_1ExecutionEngine.html#a8 > > > Note that the C calling convention do not map directly to LLVM IR for many > cases, so it's best to stick to simple parameter types (pointers and ints, > for example) and also to verify that the LLVM FunctionTypes you use are > correct on each platform you support. > > Good luck! > > — Gordon > > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > >
Hi, I have tried to use LLVM to compile a small C project. All thing seem ok, but I found some bistcast and call instructions that are weird. First, I have a simple function : void type and no parameter (content of the function is not relevant here, just copy&paste) void openBMPJPG() { bmpheader=&_bmpheader; jpegoutput=&_jpegoutput; getbmpheader(bmpheader); jpegheadersize = writejpegheader(bmpheader, &_jpegheader); _jpegoutput.header = _jpegheader; } The function is declared in a header file. After linking all the files together, the callee function is called in the way bellow: call void (...)* bitcast (void ()* @openBMPJPG to void (...)*)( ) nounwind The function has been casted to a constant before (a CE_GEP) and then this CE_GEP has been called, not the global function. I don't understand, why and how it has been casted. Can anybody explain it ? Thank for any advice Quang -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080819/0d0efa23/attachment.html>
Hello,> The function is declared in a header file.How? As 'void openBMPJPG()' ?> After linkingall the files together, the callee function is called in > the way bellow:'void openBMPJPG()' will give you varargs function declaration. So, actually you're calling no-args function via vargargs declaration. Thus bitcast there. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University.
> 'void openBMPJPG()' will give you varargs function declaration. So, > actually you're calling no-args function via vargargs declaration. Thus > bitcast there.So, the correct way of declaring the function would be void openBMPJPG(void) Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080820/1e036bbe/attachment.sig>
Apparently Analagous Threads
- [LLVMdev] Please help with LLVM C++ integration
- [LLVMdev] missed optimizations
- [LLVMdev] missed optimizations
- [LLVMdev] [DragonEgg] Why Fortran's "call flush()" is converted to "call void bitcast (void (...)* @_gfortran_flush_i4 to void (i8*)*)(i8* null) nounwind" ?
- [LLVMdev] [DragonEgg] Why Fortran's "call flush()" is converted to "call void bitcast (void (...)* @_gfortran_flush_i4 to void (i8*)*)(i8* null) nounwind" ?