I've been trying to get LLVM JIT compilation working on Android for the last few days. The patch I needed to get it to build is attached (nothing major - CMake configuration header typo and avoiding open64 which is missing on Android).
Sadly even though it builds I can't get generated code to work - it appears at the moment that the generated code doesn't have execute permissions set for some reason (this is 3.3, not svn).
llvm-android.patch (1.61 KB)
You may have a look at the LLVM Linux builds (
http://llvm.linuxfoundation.org/index.php/Main_Page), it might help you
getting Android compiled with LLVM.
The CMake changes look fine to me, landed in r194051!
As for the JITMemoryManager.cpp changes, not so sure. Did you try disabling the ‘hack’ described below instead of patching it?
// Function stubs that are invoked instead of certain library calls
// Force the following functions to be linked in to anything that uses the
// JIT. This is a hack designed to work around the all-too-clever Glibc
// strategy of making these functions work differently when inlined vs. when
// not inlined, and hiding their real definitions in a separate archive file
// that the dynamic linker can't see. For more info, search for
// 'libc_nonshared.a' on Google, or read .
^ ie try making this defined(linux) && !defined(BIONIC)
I'm trying to build LLVM on Android rather than the other way around! Really just to see if it can be done. I worked out the first problem (my code was written for the old JIT and I'd missed something in updating to the MCJIT to make it work on ARM). It still doesn't work, but at this point I have no idea why and it'll be a while before I get to look at it again: the Android debug tools simply crash and give no output whatsoever, so all I know is that the test app exits somewhere inside MCJIT::finalizeObject.
I suppose I was just doing the "smallest" thing. Disabling the hack entirely also allows it to build and is probably the correct thing to do. I'm not that knowledgeable about glibc vs. Bionic differences so the thing to do would be to test whether those functions work without the "hack" on Android. Unfortunately at the moment I can't get my Android JIT test program to actually run; it crashes somewhere in LLVM without any useful output (the debugger also crashes), so that one's going to take some time to figure out.
I suppose I was just doing the "smallest" thing. Disabling the hack
entirely also allows it to build and is probably the correct thing to
do. I'm not that knowledgeable about glibc vs. Bionic differences so
the thing to do would be to test whether those functions work without
the "hack" on Android. Unfortunately at the moment I can't get my
Android JIT test program to actually run; it crashes somewhere in LLVM
without any useful output (the debugger also crashes), so that one's
going to take some time to figure out.
Good luck with that. I can't help there (there are probably others on
the list who could/should!) but I am interested in cleaning up
The defined(__linux__) checks in LLVM aren't very consistent. Some check
for __GNU__, others for __ANDROID__ and it's known to break non-standard
So if anyone's building against ulibc, dietlibc, musl etc. and
interested in helping out with these, give me a shout.
Ha, yes, I always get confused.
You should communicate with Anton (cc'd), as he was trying to do exactly
that a few days ago. I'm also copying the LLVMLinux list, since this is the
second thread on the subject in a short time, there might be some trend to
make it work and add a buildbot or something like that.
I think that, on the Android front, it would be really nice to have
Clang/LLVM working well, especially on the JIT front, so that we could have
a more generic JIT experience, rather than just Renderscript. We should
think about that when creating AOSP images in the future.
Is it possible to try your program on a non-Android Linux? It might make debugging a bit less painful.
If you haven’t updated to the trunk code recently, it’s possible that calling finalizeObject more than once would cause a crash. The changes that introduced multiple module support should have fixed that issue.
It might be useful to set breakpoints in the memory manager you are using. During finalizeObject you are likely to see calls to finalizeMemory, getSymbolAddress, registerEHFrames and notifyObjectLoaded. I think registerEHFrames is the most likely source of the problem, particularly given that the debugger is also crashing. If that’s the problem, you could probably get a little further (for experimental purposes at least) by just having the memory manager do nothing in response to that call.
This is getting a bit off-topic, but since Renato brought up RenderScript, I wonder if the Android libbcc interface wouldn’t be a cleaner way to approach this problem. It provides more or less the same functionality as MCJIT and in almost the same way.
I don’t have another hardware ARM system, but I got it working under a qemu ARM system before trying Android and there are no issues there. I’m only putting one module in the JIT, so that shouldn’t be the issue; thanks for the registerEHFrame suggestion though. I won’t get time to try it until the weekend though.
Actually libbcc doesn’t provide the same interface as MCJIT (it is definitely ahead-of-time compilation). It also inserts many RenderScript-specific passes into the compilation, so I don’t think it would be all that useful.