Hi,
I'm still figuring how to pass functions from my c++ application (which acts as a host to a clang JIT) to the JIT.
Obviously this is possible using extern "C" declarations, but I don't want to declare or wrap everything like this and I'd like to overload functions as well.
Now as far as I understand this stuff it should be possible to mangle the name and export the functions with their mangled names.
Also from scrolling through the doxygen documentation it seems to me that there are routines in clang (probably even llvm itself) to do the mangling.
But I have no clue how to use them - are the even part of the API?
I'd prefer calling the llvm/clang internal routined for obvious reasons of compatibility. Beyond that I'm not really afraid of any compatibility issues (should I?), as the host application will be compiled with gcc or llvm-gcc or even clang (as soon as it does Qt, fully).
So I'd be grateful for any advise how to achieve the name mangling.
-Frank
I'm not clear on what you're asking. As far as I understand, you're using clang in-process to generate LLVM IR for C++ source code, which you are then going to feed to the JIT. You're compiling this code in some way such that it produces references to global variables/functions, which you'd then like to map in the JIT to functions already compiled in your program, and in order to perform this mapping you want to re-mangle the global declarations you know about to see what names they come out to. Am I understanding this correctly?
John.
Well if I understand your view on it correctly then … yes that is what I’m trying to do. However, please allow me to give a more long winded description of what I want to do. So I have a rather large Qt/C++ application and I want to give it some scripting powers (make its computational core scriptable from within the application itself). I first tried to embed some script language (QtScript and Chaiscript), but they did not convince me in terms of their features and performance (although I must say that I liked both approaches anyway). Now I want to embed clang into my application to execute small C++ scripts/ user supplied methods. In the examples for clang there is an app for that ;), well almost. The clang-interpreter example takes C/C++ code compiles and runs it. Now the “only” thing I have to do is to enhance it by exposing my host application methods to the jitted user supplied scripts. It can be done by either wrapping all of my methods in extern “C” functions. But this is not what I want.
If I drop the extern “C” and use C++ headers instead I get error messages like “LLVM error: program used external function ‘_Z10testCallerv()’ which could not be resolved”. Of course it could not be resolved … since I was not able/willing to guess the name-mangling while declaring the the external function to the clang-interpreter. I used declared “void testCaller()”. Now if I change my declaration to the mangled name it works. I can call C++ methods which reside in the host-application from my scripts. However, I do not want to mangle all the names of my to-be exposed functions by hand. There must be a method for that as well - clang must have it already.
-Frank
PS: @John sorry for the second mail I forgot to include the cfe-list
2010/7/15 John McCall <rjmccall@apple.com>
I actually recently introduced a hack to support this sort of in-process JITting (to support LLDB, which does something similar). It's not at all documented, and (like most of Clang's APIs) it's subject to change at a whim, but it's probably easier than repeatedly mangling things. When setting up your environment, set the EmitDeclMetadata flag on the CodeGenOpts. After compilation, the module will have a named metadata called "clang.global.decl.ptrs"; each of the operands of that will be a ConstantStruct containing a GlobalValue and a ConstantInt whose value can be casted to Decl*. Not the prettiest interface imaginable, but it's there.
That said, I would really recommend Lua if you're looking for an embedded scripting language and you don't need native-code performance. It's a *lot* safer than letting users run arbitrary C++ code within your process.
John.
Ok I need and want native performance - it’s a scientific application and although very complex things will be referred to the core methods I cannot stop users from writing large loops and complain about the performance. In the worst case they crash the whole thing … but I’m willing to take that risk :D.
Now concerning your answer I do not see how it might help me. If I understand it correctly you have implemented a way to get information about the Decl of jitted methods. Now how does that help me, because I still think I need to declare the mangled names to the JIT, and for this purpose I need to now them at compile time of the host application.
thx,Frank
2010/7/16 John McCall <rjmccall@apple.com>
Ok I need and want native performance - it's a scientific application and although very complex things will be referred to the core methods I cannot stop users from writing large loops and complain about the performance. In the worst case they crash the whole thing ... but I'm willing to take that risk :D.
Well, your call.
Now concerning your answer I do not see how it might help me. If I understand it correctly you have implemented a way to get information about the Decl of jitted methods. Now how does that help me, because I still think I need to declare the mangled names to the JIT, and for this purpose I need to now them at compile time of the host application.
Oh, are you just asking for a way to figure out a mangling statically? I'm sorry, I really thought you were trying to do this dynamically. I'm afraid there really isn't a convenient way of getting a mangling for a declaration string from the command line. It'd be a fun little hack, but nobody's done it yet.
Honestly, I'd suggest just looking in your executable: if you know what .o file contains that symbol, just nm that file and grep for the name, which is always a substring of the mangling.
For example, there's a method on Sema called GetTypeForDeclarator that's implemented in SemaType.cpp.
% nm lib/Sema/Debug+Asserts/SemaType.o | grep GetTypeForDeclarator
00000000001ebd90 s L___func__._ZN5clang4Sema20GetTypeForDeclaratorERNS_10DeclaratorEPNS_5ScopeEPPNS_7TagDeclE
0000000000002670 T __ZN5clang4Sema20GetTypeForDeclaratorERNS_10DeclaratorEPNS_5ScopeEPPNS_7TagDeclE
00000000001eea38 S __ZN5clang4Sema20GetTypeForDeclaratorERNS_10DeclaratorEPNS_5ScopeEPPNS_7TagDeclE.eh
The function is the one in the middle; the mangled name is that, minus the first leading underscore.
John.
There are several problems with what you are trying to do,
Firstly it will only work with gcc or something that uses exactly the
same ABI as clang so for now no MSVC
secondly the JIT is supposed to be able to use dlsym to resolve
functions at runtime but this only works on non windows,
Putting manglings into your code manually is horrible and will only
break stuff down the road.