Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building V8 with Clang and emitting LLVM IR

I am attempting to build the V8 Javascript engine with Clang and output an .ll file(s). I am trying to combine the information here and here to do this. However, when I try to make, it fails, saying "No rule to make target." I am lost. I've tried just compiling v8.cc, but that just totally fails. I imagine it's because I'm trying to force -emit-llvm by putting it in as the compiler, but I'm not sure.

$ cd v8
$ export CXX="clang++ -S -emit-llvm"
$ export CC="clang -S -emit-llvm"
$ export CPP="clang -E -S -emit-llvm"
$ export LINK="clang++ -S -emit-llvm"
$ export CXX_host="clang++ -S -emit-llvm"
$ export CC_host="clang -S -emit-llvm"
$ export CPP_host="clang -E -S -emit-llvm"
$ export LINK_host="clang++ -S -emit-llvm"
$ export GYP_DEFINES="clang=1"
$ make native
PYTHONPATH="/home/pitaj/v8/tools/generate_shim_headers:/home/pitaj/v8/build::/home/pitaj/v8/build/gyp/pylib:" \
    GYP_GENERATORS=make \
    build/gyp/gyp --generator-output="out" build/all.gyp \
                  -Ibuild/standalone.gypi --depth=. -S.native  -Dv8_enable_backtrace=1 -Darm_fpu=default -Darm_float_abi=default
make[1]: Entering directory `/home/pitaj/v8/out'
  CXX(target) /home/pitaj/v8/out/native/obj.target/v8_base/src/accessors.o

... (bunch more CXX calls, full output here) ...

  CXX(target) /home/pitaj/v8/out/native/obj.target/v8_base/src/utils.o
make[1]: *** No rule to make target `/home/pitaj/v8/out/native/obj.target/v8_base/src/v8.o', needed by `/home/pitaj/v8/out/native/obj.target/tools/gyp/libv8_base.a'.  Stop.
make[1]: Leaving directory `/home/pitaj/v8/out'
make: *** [native] Error 2

EDIT:

Makefile: http://pastebin.com/PsZrCkzE

EDIT2:

The following builds v8 without errors, but obviously doesn't emit any IR.

$ cd v8
$ export CXX="clang++"
$ export CC="clang"
$ export CPP="clang -E"
$ export LINK="clang++"
$ export CXX_host="clang++"
$ export CC_host="clang"
$ export CPP_host="clang -E"
$ export LINK_host="clang++"
$ export GYP_DEFINES="clang=1"
$ make native
like image 860
PitaJ Avatar asked Jul 18 '14 05:07

PitaJ


1 Answers

C and C++ Compilers generally have 4 stages:

  1. Pre-process
  2. Compile source to assembler
  3. Assemble assembler to binary object files
  4. Link multiple object files to produce one executable, shared library or static library

In the case of clang, stage 2 is kind of split: first produce LLVM IR, then assemble that into assembly for the target architecture.

clang and gcc both share the same command line options to control which stage will be executed:

  • -E runs only the preprocessor stage
  • -S runs preprocess and compile stage, outputting assembly files
  • -c runs preprocess, compile and assemble stages, producing a .o object file
  • If you do not include any of these options, then it will also link to produce an executable (or, depending on other options, a static or shared library).

The -emit-llvm option affects only the compile stage, and must be used in conjunction with the -S option. Adding these options mean that when the compiler is called, it produces a single file containing LLVM IR. The default output filename would be the same as the input filename but with .ll as the extension.

The gyp tool does not actually build the project. Rather, it produces a set of makefiles, which do the actual build. These makefiles contain rules for building one type of needed file from another. The main rules are:

  1. Produce .o files from .cpp input files (equivalent to stages 1-3 above, for each .cpp file)
  2. Produce static (.a) &/or dynamic (.so) library files from the object files

The environment variables, which you have modified, affect the commands used in these rules. Specifically, the CXX variable specifies the command used for the first rule above.

Another thing to note is that the Makefile rule for compilation adds the -o option to the command which overrides the output filename. So, when it is executing this rule using the CXX environment variable setting you have specified, it is actually producing LLVM IR files, but naming them .o instead of .ll.

The problems occur when make gets to the next stage and tries to make .a or .so files out of these object files - since they are not really object files, but LLVM IR files.

But the good news is, according to your own question, you only want the LLVM IR files anyway. By the time it gets to the failure, it has already produced those. The only catch is they are named with .o instead of .ll, but hey, you can easily rename them.

If you want the build to proceed cleanly to the end, you can suppress the production of library files by changing the commands used for linking and archiving to 'true', which does nothing:

cd v8
export CXX="clang++ -S -emit-llvm"
export CC="clang -S -emit-llvm"
export CPP="clang -E"
export LINK="true"
export AR="true"
export CXX_host="clang++ -S -emit-llvm"
export CC_host="clang -S -emit-llvm"
export CPP_host="clang -E"
export LINK_host="true"
export AR_host="true"
export GYP_DEFINES="clang=1"
make native

As I say, at the end of the build you will have one .o file for each of the .cpp files - the filenames will be printed during compilation. These will actually be LLVM IR files. You can rename them with:

find out/native/obj.target/ -name "*.o" -exec rename .o .ll \{\} \;
like image 108
harmic Avatar answered Nov 15 '22 14:11

harmic