JIT on ARM

Hello.

My goal is to use LLVM with JIT compiler for ARM on Android device.

Currently I have successfully built and executed LLVM bitcode with interpreter on Android. Speed is not so great, that is why I want to use JIT.
I tried building bitcode on windows with llvm-gcc that is provided on llvm home page. Resulting bitcode runs great in interpreter, but it doesn't use JIT. From what I understand from LLVM that it is because of target triple or datalayout. On PC in my case target triple is "i386-mingw32", but LLVM JIT for ARM expects something that starts with "armv" or "thumb". Also datalayout differs a lot. If I understand correctly that is because bitcode actually contains some of platform specific optimizations (like integer endianness), so I can't simply change target triple string and everything will run.

What I am now doing, is - I am trying to build gcc from gcc-4.2-llvm-2.5 sources with following configure line in cygwin shell:

../llvm-gcc4.2-2.4.source/configure --enable-languages=c,c++ --enable-checking --enable-llvm=$PWD/../llvm-objects --disable-bootstrap --disable-multilib --disable-nls --target=arm-eabi

My undertanding is that this will produce llvm-gcc compiler that will output LLVM bitcode with target triple that starts with "arm", so LLVM will use JIT on it.

Currently I am getting compile problems when running make (see below).
Has anyone done something similar and can explain what I am doing wrong, or how should it be done in some other way to get JIT compiler running on ARM?

make[2]: Entering directory `/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc'
gcc -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute -fno-common -DHAVE_CONFIG_H -DGENERATOR_FILE -o build/gengtype.exe \
             build/gengtype.o build/gengtype-lex.o build/gengtype-yacc.o build/errors.o ../build-i686-pc-cygwin/libiberty/libiberty.a
build/gengtype.o: In function `adjust_field_type':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:763: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:771: undefined reference to `_lexer_line'
build/gengtype.o: In function `adjust_field_tree_exp':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:713: undefined reference to `_lexer_line'
build/gengtype.o: In function `adjust_field_rtx_def':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:488: undefined reference to `_lexer_line'
build/gengtype.o: In function `adjust_field_type':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:785: undefined reference to `_lexer_line'
build/gengtype.o:/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:725: more undefined references to `_lexer_line' follow
build/gengtype.o: In function `main':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:3070: undefined reference to `_parse_file'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:3070: undefined reference to `_parse_file'
build/gengtype-yacc.o: In function `yyparse':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:73: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:75: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:76: undefined reference to `_lexer_toplevel_done'
build/gengtype-yacc.o: In function `yyparse':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/gengtype-yacc.c:1873: undefined reference to `_yyerror'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/gengtype-yacc.c:1379: undefined reference to `_yylex'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/gengtype-yacc.c:1877: undefined reference to `_yyerror'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/gengtype-yacc.c:1995: undefined reference to `_yyerror'
build/gengtype-yacc.o: In function `yyparse':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:122: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:110: undefined reference to `_lexer_toplevel_done'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:102: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:97: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:92: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:239: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:235: undefined reference to `_lexer_line'
build/gengtype-yacc.o:/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:231: more undefined references to `_lexer_line' follow
build/gengtype-yacc.o: In function `yyparse':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:84: undefined reference to `_lexer_toplevel_done'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:203: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:203: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:176: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:176: undefined reference to `_lexer_line'
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:165: undefined reference to `_lexer_line'
build/gengtype-yacc.o:/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype-yacc.y:165: more undefined references to `_lexer_line' follow
collect2: ld returned 1 exit status
make[2]: *** [build/gengtype.exe] Error 1

Hi.
Sorry for reposting my mail, but can somebody at lest give some general ideas for what to look to solve my problem?

Hi Martins,

I tried building bitcode on windows with llvm-gcc that is provided on llvm home page. Resulting bitcode runs great in interpreter, but it doesn't use JIT. From what I understand from LLVM that it is because of target triple or datalayout. On PC in my case target triple is "i386-mingw32", but LLVM JIT for ARM expects something that starts with "armv" or "thumb". Also datalayout differs a lot. If I understand correctly that is because bitcode actually contains some of platform specific optimizations (like integer endianness), so I can't simply change target triple string and everything will run.

as you have understood, the JIT requires bitcode that targets the
machine you are jiting on, so you need to cross-compile for arm.
I don't know anything about cross-compiling, for example whether
it is possible and whether you are doing it right - hopefully one
of the arm guys can help you out.

Ciao,

Duncan.

What I am now doing, is - I am trying to build gcc from gcc-4.2-llvm-2.5 sources with following configure line in cygwin shell:

../llvm-gcc4.2-2.4.source/configure --enable-languages=c,c++ --enable-checking --enable-llvm=$PWD/../llvm-objects --disable-bootstrap --disable-multilib --disable-nls --target=arm-eabi

My undertanding is that this will produce llvm-gcc compiler that will output LLVM bitcode with target triple that starts with "arm", so LLVM will use JIT on it.

Currently I am getting compile problems when running make (see below).
Has anyone done something similar and can explain what I am doing wrong, or how should it be done in some other way to get JIT compiler running on ARM?

make[2]: Entering directory `/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc'
gcc -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute -fno-common -DHAVE_CONFIG_H -DGENERATOR_FILE -o build/gengtype.exe \
           build/gengtype.o build/gengtype-lex.o build/gengtype-yacc.o build/errors.o ../build-i686-pc-cygwin/libiberty/libiberty.a
build/gengtype.o: In function `adjust_field_type':
/cygdrive/r/android/llvm/llvm-gcc4.2-objects/gcc/../../llvm-gcc4.2-2.4.source/gcc/gengtype.c:763: undefined reference to `_lexer_line'

...

Hi Martins,

There's two steps to get where you're wanting to go.

First, you need an ARM cross-compiler on your host so you can generate ARM bitcode. That's what you're building with your llvm-gcc you referenced. In my ARM configure lines, I explicitly specify --host and --build as well as --target, but that is more due to vagaries of my local environment and shouldn't be required for what you're doing.

Second, you need an ARM *hosted* LLVM build to actually do the JIT execution of the bytecode you've produced on the host. For that, you'll need a canadian-cross compile build of llvmCore. Have a separate objects build directory for llvm than you use for cross compiler since this will be ARM code, not x86 code. Specify "--host=arm-eabi --build=i686-pc-cygwin --target=arm-eabi" on your configure line, and you should be able to generate an ARM-hosted LLVM toolset. Do note that this will require a set of ARM-target cross compiler tools to be on the path and ARM libraries to be available, just like building any other ARM code on your host. You'll see the configure script looking for tools like "arm-eabi-gcc" and such, probably. If it can't find them, things are unlikely to work.

Once you've built the ARM hosted LLVM, you can copy it over to your device (I NFS mount the directory, personally). Then you can run lli from there on bitcode and the ARM JIT should kick in and compile your code.

The errors you're seeing don't look familiar to me, unfortunately. lexer_line is defined in gengtype-lex.l. Perhaps there were issues running flex to generate the code from there? I would suggest looking in your build logs for where gengtype-lex.c and gengtype-lex.o are created to see if there are earlier problems that cascaded down to result in this link failure.

Regards,
   Jim

Forgot to mention. I don't know how well the canadian cross compile stuff works in 2.5. We made some improvements in that area for 2.6. If you have trouble with it, I'd suggest trying 2.6 (or even better, ToT svn) and seeing if things are improved there.

-Jim

Ok, thanks for answers. I will try to do things you suggested.

I found out that even calling functions that are defined inside LLVM bitcode doesn’t work.
So following C code when compiled without any optimizations also crashes with JIT when main function is called (with optimizations function call is optimized away, of course).