192

I want clang to compile my C/C++ code to LLVM bitcode rather than a binary executable. How can I achieve that?

And if I have the LLVM bitcode, how can I further compile it to a binary executable?

I want to add some of my own code to the LLVM bitcode before compiling to a binary executable.

janw
  • 8,758
  • 11
  • 40
  • 62
pythonic
  • 20,589
  • 43
  • 136
  • 219

5 Answers5

256

Given some C/C++ file foo.c:

> clang -S -emit-llvm foo.c

Produces foo.ll which is an LLVM IR file.

The -emit-llvm option can also be passed to the compiler front-end directly, and not the driver by means of -cc1:

> clang -cc1 foo.c -emit-llvm

Produces foo.ll with the IR. -cc1 adds some cool options like -ast-print. Check out -cc1 --help for more details.


To compile LLVM IR further to assembly, use the llc tool:

> llc foo.ll

Produces foo.s with assembly (defaulting to the machine architecture you run it on). llc is one of the LLVM tools - here is its documentation.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • 12
    What does -S do here? – meawoppl Feb 27 '14 at 16:17
  • 22
    @meawoppl: -S like in gcc says emit textual assembly rather than assembled binary – Eli Bendersky Feb 28 '14 at 16:53
  • Ahha. I was having a hard time finding anything in the docs about it. It is safe to assume that many flags in clang mirror gcc flag structure? – meawoppl Feb 28 '14 at 17:35
  • 1
    @EliBendersky Do you know how to compile multiple .c and .h files into one human readable IR so that I can run the IR using 'lli theIrFile'? Thanks – cache Jul 20 '14 at 18:43
  • 4
    @cache: compile each into its own IR file and then use the LLVM linker to combine – Eli Bendersky Jul 22 '14 at 03:12
  • Bitcode files can be compiled with `clang` directly (omitting `llc`). `llc` has different cmdline flags and different pipeline so normally it's more of an annoyance. – yugr Jun 19 '19 at 09:22
  • For anyone that needs llvm bytecode in a cmake project: `-emit-llvm` can't be used in `CLANG_CXX_FLAGS`, because clang crashes if the flag is passed for linking. I used `-save-temps` instead, which did not break anything. Note that this does not create `.ll` files and requires using `llvm-dis` to translate `.bc` to `.ll`. – Julius Naeumann Mar 30 '23 at 15:58
27

If you have multiple source files, you probably actually want to use link-time-optimization to output one bitcode file for the entire program. The other answers given will cause you to end up with a bitcode file for every source file.

Instead, you want to compile with link-time-optimization

clang -flto -c program1.c -o program1.o
clang -flto -c program2.c -o program2.o

and for the final linking step, add the argument -Wl,-plugin-opt=also-emit-llvm

clang -flto -Wl,-plugin-opt=also-emit-llvm program1.o program2.o -o program

This gives you both a compiled program and the bitcode corresponding to it (program.bc). You can then modify program.bc in any way you like, and recompile the modified program at any time by doing

clang program.bc -o program

although be aware that you need to include any necessary linker flags (for external libraries, etc) at this step again.

Note that you need to be using the gold linker for this to work. If you want to force clang to use a specific linker, create a symlink to that linker named "ld" in a special directory called "fakebin" somewhere on your computer, and add the option

-B/home/jeremy/fakebin

to any linking steps above.

Jeremy Salwen
  • 8,061
  • 5
  • 50
  • 73
24

If you have multiple files and you don't want to have to type each file, I would recommend that you follow these simple steps (I am using clang-3.8 but you can use any other version):

  1. generate all .ll files

    clang-3.8 -S -emit-llvm *.c
    
  2. link them into a single one

    llvm-link-3.8 -S -v -o single.ll *.ll
    
  3. (Optional) Optimise your code (maybe some alias analysis)

    opt-3.8 -S -O3 -aa -basicaaa -tbaa -licm single.ll -o optimised.ll
    
  4. Generate assembly (generates a optimised.s file)

    llc-3.8 optimised.ll
    
  5. Create executable (named a.out)

    clang-3.8 optimised.s
    
Kiko Fernandez
  • 857
  • 10
  • 26
  • 1
    Your solution is quite unique: you used "-S" instead of just leaving it as binary output. Is there any difference between having "-S" and not having "-S"? – Peter Teoh Sep 24 '17 at 01:46
  • 1
    @PeterTeoh I use the `-S` option (in step 2), I specify that I would like to produce the output in LLVM IR. Basically, put all *.ll files into a single one. I do this to check that the optimisations really change the code, i.e. `single.ll` and `optimised.ll` should now look different (code-wise) and you could also show the report to see if there is any difference at all. – Kiko Fernandez Oct 16 '17 at 07:39
  • 1
    `-basicaaa` is a wrong flag, `-basicaa` must be used instead. – anton_rh Jul 14 '19 at 11:35
24

Use

clang -emit-llvm -o foo.bc -c foo.c
clang -o foo foo.bc
Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 9
    I'd recommend to keep extension meanings intact. IOW, `.o` should refer to binary object files, `.s` to assembly files, and something else (by convention `.ll`) to LLVM IR files. Otherwise it's easy to get confused. Clang/LLVM now have no linker of their own for binary objects (though one is in the works). The LLVM linker `llvm-ld` just joins several IR files into one – Eli Bendersky Feb 05 '12 at 13:06
  • 2
    @EliBendersky: you're correct where file extensions are concerned - and the clang frontend actually does the right thing if `.bc` is used; also, keep in mind that `llvm-ld` can act as frontend for the system toolchain, ie my previous answer using `llvm-ld -native` should work as expected.... – Christoph Feb 05 '12 at 13:13
  • 1
    @rickfoosusa: works for me - `foo.bc` is an LLVM bitcode file – Christoph Sep 25 '14 at 21:23
  • 1
    Works for me: `clang -emit-llvm -o test.bc -c test.c && file test.bc: test.bc: LLVM IR bitcode`. – ntc2 Apr 12 '16 at 17:11
14

Did you read clang documentation ? You're probably looking for -emit-llvm.

rotoglup
  • 5,223
  • 25
  • 37