Getting LLVM bit-code for programs using a couple of libraries

Hi guys,

I am compiling some programs with clang which use a couple of
libraries. When I compile with the command - "clang -O2 -I. -o hello
-ldl -llttng-ust hello.c tp.c", it goes successful.

My aim is to get the bitcode for these programs but if I try to
generate the bitcode with -emit-llvm option, it produces linking
issues as follows : (also at - sandeep@ubuntu:~/lttng-git/lttng-ust/tests/hello2$ clang -emit-llvm -O2 -I. -o h - Pastebin.com)

sandeep@ubuntu:~/lttng-git/lttng-ust/tests/hello2$ clang -emit-llvm
-O2 -I. -o hello -ldl -llttng-ust hello.c tp.c
/usr/bin/ld: error: /tmp/hello-u3dmcq.o:1:3: invalid character
/usr/bin/ld: error: /tmp/hello-u3dmcq.o:1:3: syntax error, unexpected $end
/usr/bin/ld: error: /tmp/hello-u3dmcq.o: not an object or archive
/usr/bin/ld: error: /tmp/tp-1CR8ta.o:1:3: invalid character
/usr/bin/ld: error: /tmp/tp-1CR8ta.o:1:3: syntax error, unexpected $end
/usr/bin/ld: error: /tmp/tp-1CR8ta.o: not an object or archive
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o(.text+0x20):
error: undefined reference to 'main'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

What is a way to go around these linking issues?

Also, I can successfully generate bitcode for a simple hello-world
program using the -emit-llvm program so I installation of clang/llvm
on my system is good.

PS: I hope that I am not mistaken in posting this query here. But if
I'am, please excuse me.

Thanks and regards,
Sandeep.

Can someone please help me with it?

Thanks and regards,
Sandeep.

Hi Sandeep,

My aim is to get the bitcode for these programs but if I try to
generate the bitcode with -emit-llvm option, it produces linking
issues as follows : (also at - sandeep@ubuntu:~/lttng-git/lttng-ust/tests/hello2$ clang -emit-llvm -O2 -I. -o h - Pastebin.com)

You shouldn't really expect "-emit-llvm" to work well with an existing
build system. That flag means the normal .o files produced by clang
will be LLVM bitcode *instead* of ELF (or whatever). This happens to
be the norm with "-flto" compilations, but that needs a compatible
linker and really it needs clang to know that's what it's doing (i.e.
-flto at *all* stages of compilation).

If you just want the LLVM IR for a reasonably large project, you
should probably setup a parallel set of "build" steps that produce the
IR but aren't involved in the actual compilation.

Mostly I find I want it just for one file occasionally. So I just
copy/paste the command-line and add -emit-llvm manually (usually with
"-S -o-" because I want to see it *now*).

Cheers.

Tim.

Thank you so much for the reply, Tim ! I have some follow up questions
(in the inline replies), it would be great if you can answer those.

Hi Sandeep,

My aim is to get the bitcode for these programs but if I try to
generate the bitcode with -emit-llvm option, it produces linking
issues as follows : (also at - sandeep@ubuntu:~/lttng-git/lttng-ust/tests/hello2$ clang -emit-llvm -O2 -I. -o h - Pastebin.com)

You shouldn't really expect "-emit-llvm" to work well with an existing
build system. That flag means the normal .o files produced by clang
will be LLVM bitcode *instead* of ELF (or whatever). This happens to
be the norm with "-flto" compilations, but that needs a compatible
linker and really it needs clang to know that's what it's doing (i.e.
-flto at *all* stages of compilation).

Does it mean that I need to give -flto option for compilation while
building the libraries that I am using i.e. lttng-ust and libdl?

If you just want the LLVM IR for a reasonably large project, you
should probably setup a parallel set of "build" steps that produce the
IR but aren't involved in the actual compilation.

So, does it mean adding -flto option in each build step? Can you
please explain this a bit? I mean - how to set up such a parallel set
of builds in my case?

Mostly I find I want it just for one file occasionally. So I just
copy/paste the command-line and add -emit-llvm manually (usually with
"-S -o-" because I want to see it *now*).

Yeah, getting the bit-code for just one file is straight forward as
you mentioned. :slight_smile:

Hi Sandeep,

Does it mean that I need to give -flto option for compilation while
building the libraries that I am using i.e. lttng-ust and libdl?

No, you can mix and match lto and non-lto files & libraries.

If you just want the LLVM IR for a reasonably large project, you
should probably setup a parallel set of "build" steps that produce the
IR but aren't involved in the actual compilation.

So, does it mean adding -flto option in each build step? Can you
please explain this a bit? I mean - how to set up such a parallel set
of builds in my case?

You need a compatible linker (which means ld.gold or a recent ld.bfd,
I don't know the version off the top of my head). You then need to add
"-flto" to both compile and link steps. With luck, that will just
work. For example, with a trivial single file:

$ clang -c -O3 -flto hello.c
$ clang -flto hello.o -ohello

But I realise I didn't say what -flto was: it's link-time
optimization. Generally the code you get out is better, but it incurs
significant memory and build time overheads. It may not be practical,
depending on the size of your project.

Cheers.

Tim.

Hi Tim,

Thanks a lot for the replies, and the clarification !

I can now try these things.

Thanks and regards,
Sandeep.

Dear Sandeep,

There are a couple of ways to get what you want, depending on what you want to do.

If you want to run LLVM's link-time optimization passes, then following the suggestion of using libLTO to just transparently link together files generated by clang -flto is the best way to go.

If you want to write a new optimization and have it run at link time, then your best bet is to modify libLTO to run your new optimization pass.

If you really just want a single bitcode file for a program, you could modify libLTO to run a pass that will dump the linked LLVM IR bitcode to a file. I believe one of our students (now a postdoc) tried that approach. Alternatively, you can change the application's Makefiles to use -emit-llvm, but that may be more work (depending on the program).

Hope this helps,

John Criswell