Using llvm-gcc with a simple program and the '-c' option

Hello,

When I compile a "hello.c" program with a printf in "main" and use llvm-gcc with a "-c" option:

    llvm-gcc -c t1.c -o t1.bc

and then try to compile t1.bc to native using llc & gcc I get a call to "__main" which is undefined.

If I don't use the "-c" option:

    llvm-gcc t1.c -o t1

I don't get a reference to "__main" and I can compile to native without problem. Also, I created some simple modules without a "main" and using the "-c" option and that works as expected. What am I doing wrong?

Thanks,

Wink Saville

The -c option tells llvm-gcc to build a bytecode file without linking in the LLVM runtime library. This is similar to the -c option for regular gcc, which you use to build multiple separate .o files that you're going to link into a single executable. If you want to build from a single source file, it's easiest just to compile without the -c option. If you're building from multiple source files, you can either give them all to llvm-gcc at the same time with no -c option

  llvm-gcc foo.c bar.c -o foobar

or compile separately with -c and then link them together

  llvm-gcc -c foo.c -o foo.bc
  llvm-gcc -c bar.c -o bar.bc
  llvm-gcc foo.bc bar.bc -o foobar

You can also use llvm-ld for the last step.

Rob

Robert,

Thanks for the info, you've confirmed what I was trying to do, but when I compile:

Thanks for the info, you've confirmed what I was trying to do, but when
I compile:

[snip]

without "-c" (llvm-gcc t1.c -o t1) the dissassembled bytecode does not
call __main:

__main() is used to run static constructors and destructors, so if
you're compiling without -c, LLVM knows all the files you're compiling
and if there are no static constructors, __main() is not necessary (or
if it's there, it's empty, and can be inlined into a no-op).

[snip]

But if I use the "-c" option (llvm-gcc -c t1.c -o t1.bc) the bytecode
is:

If you're using -c, you're telling LLVM that there are other modules you
will link into the executable. Thus, LLVM does not know whether there
will be static ctors/dtors to run or not, so there's the call to
__main() from main.

__main() gets linked into your program if you use gccld (which is what
llvm-gcc uses) or llvm-ld manually. The __main() itself comes from one
of the runtime libraries: llvm/runtime/GCCLibraries/crtend/crtend.c .

Misha Brukman wrote:

  

[snip]

If you're using -c, you're telling LLVM that there are other modules you
will link into the executable. Thus, LLVM does not know whether there
will be static ctors/dtors to run or not, so there's the call to
__main() from main.

__main() gets linked into your program if you use gccld (which is what
llvm-gcc uses) or llvm-ld manually. The __main() itself comes from one
of the runtime libraries: llvm/runtime/GCCLibraries/crtend/crtend.c .
  
Misha,

Great now I understand, one more related question. This actually started trying to understand how llvm-gcc, llvm-ar, llvm-ld & llc work together. With the help I've received I've successfully used them to create a native executable of 3 files, t1.c, t1sub1.c t1sub2.c, where t1.c calls a subroutine in t1sub1.c and t1sub2.c.

I then do the following in my makefile:

  llvm-gcc -c t1.c -o t1.bc
  llvm-gcc -c t1sub1.c -o t1sub1.bc
  llvm-gcc -c t1sub2.c -o t1sub2.bc
  llvm-ar r t1.a t1sub1.bc t1sub2.bc
  llvm-ar: creating t1.a
  llvm-ld -o t1.app t1.bc t1.a /opt/llvm-1.6/llvm-gcc/lib/libcrtend.a
  llvm-ld: warning: Cannot find library 'crtend'
  llc t1.app.bc -o t1.app.s
  gcc -m32 t1.app.s -o t1

So a few minor problems, the first is really minor the llvm-ld command generates the t.app script that runs t1.app.bc, obviously no big deal, but isn't what I expected and would seem to be to be unnecessary. Another is the warning:

  llvm-ld: warning: Cannot find library 'crtend'

I tried:

  llvm-ld -o t1.app t1.bc t1.a -L/opt/llvm-1.6/llvm-gcc/lib -lcrtend

But that gives me two cannot find library warnings and __main is undefined. Again, the when using libcrtend.a directly everything works bit gives the warning which seems very odd as it is "obviously" there. Also, why does the second version not work?

Thanks again,

Wink

I then do the following in my makefile:

llvm-gcc -c t1.c -o t1.bc
llvm-gcc -c t1sub1.c -o t1sub1.bc
llvm-gcc -c t1sub2.c -o t1sub2.bc
llvm-ar r t1.a t1sub1.bc t1sub2.bc
llvm-ar: creating t1.a
llvm-ld -o t1.app t1.bc t1.a /opt/llvm-1.6/llvm-gcc/lib/libcrtend.a
llvm-ld: warning: Cannot find library 'crtend'

Try passing "-L/opt/llvm-1.6/llvm-gcc/lib/ -lcrtend" to llvm-ld. Alternatively, instead of using llvm-ld, just use gccld to link like this:

llvm-gcc -o t1.app t1.bc t1.a

... which should work.

llc t1.app.bc -o t1.app.s
gcc -m32 t1.app.s -o t1

If you want a native app, try this:

llvm-gcc -o t1.app t1.bc t1.a -Wl,-native

... which will invoke llc and the assembler for you. This will also fix the "script + bc" issue.

-Chris

Chris Lattner wrote:

I then do the following in my makefile:

llvm-gcc -c t1.c -o t1.bc
llvm-gcc -c t1sub1.c -o t1sub1.bc
llvm-gcc -c t1sub2.c -o t1sub2.bc
llvm-ar r t1.a t1sub1.bc t1sub2.bc
llvm-ar: creating t1.a
llvm-ld -o t1.app t1.bc t1.a /opt/llvm-1.6/llvm-gcc/lib/libcrtend.a
llvm-ld: warning: Cannot find library 'crtend'

Try passing "-L/opt/llvm-1.6/llvm-gcc/lib/ -lcrtend" to llvm-ld.

This didn't work for me:
llvm-ld -o t1.app t1.bc t1.a -L/opt/llvm-1.6/llvm-gcc/lib/ -lcrtend.a

I get two warning's about library 'crtend' missing

Alternatively, instead of using llvm-ld, just use gccld to link like this:

llvm-gcc -o t1.app t1.bc t1.a

Yes this works, but not native

... which should work.

llc t1.app.bc -o t1.app.s
gcc -m32 t1.app.s -o t1

If you want a native app, try this:

llvm-gcc -o t1.app t1.bc t1.a -Wl,-native

... which will invoke llc and the assembler for you. This will also fix the "script + bc" issue.

Yes this works and doesn't generate the script but since I'm using an amd64 with linux the result doesn't run because I need the -m32.

-Chris

Actually, the point of the above was to understand how the flow native and to see what difficulties I ran into.

Is it a bug that I get the "llvm-ld: warning: Cannot find library 'crtend'"? If so, is it likely to be in llvm code and would it be something you'd let a neophyte to track down?

Wink

You didn't get the instructions quite right. The option is -lcrtend not
-lcrtend.a

Reid.

Reid Spencer wrote:

  

Try passing "-L/opt/llvm-1.6/llvm-gcc/lib/ -lcrtend" to llvm-ld.
      

This didn't work for me:
llvm-ld -o t1.app t1.bc t1.a -L/opt/llvm-1.6/llvm-gcc/lib/ -lcrtend.a

I get two warning's about library 'crtend' missing

You didn't get the instructions quite right. The option is -lcrtend not
-lcrtend.a

Reid.
  ------------------------------------------------------------------------

_______________________________________________
LLVM Developers mailing list
LLVMdev@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
  
Actually, I didn't have the ".a" just -lcrtend.

In possibly related news I just checked out the latest llvm from cvs and compiled it. Guess what, there were 6 warnings in the output and 3 of them were "gccld: warning: Cannot find library 'crtend'". The last one was just before the end:

llvm[4]: Linking Debug Object Library stkr_compiler.o
make[4]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/lib/compiler'
make[4]: Entering directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/lib/runtime'
llvm[4]: Compiling stacker_rt.c for Debug build (bytecode)
llvm[4]: Compiling stacker_rt.ll to stacker_rt.bc for Debug build (bytecode)
llvm[4]: Building Debug Bytecode Module stkr_runtime.bc
gccld: warning: Cannot find library 'crtend'
make[4]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/lib/runtime'
make[3]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/lib'
make[3]: Entering directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/tools'
make[4]: Entering directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/tools/stkrc'
llvm[4]: Compiling stkrc.cpp for Debug build
llvm[4]: Linking Debug executable stkrc
llvm[4]: ======= Finished Linking Debug Executable stkrc
make[4]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/tools/stkrc'
make[3]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker/tools'
make[2]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects/Stacker'
make[1]: Leaving directory `/home/wink/prgs/llvm-cvs/llvm/projects'

I haven't tried seeing if anything works (getting past my bed time:), but could this have something to do with my using X86-64 (Amd64)? Also, I'm using gcc-4.0.2 and glibc appears to be 2.3.5 (symbolic link from libc.so.6 is libc-2.3.5.so).

Note: I'm new to linux, in case it wasn't obvious.

Cheers,

Wink

Did you install the bytecode? You might need to:

cd runtime ; make install-bytecode

Reid.

I would suggest hacking llvm::GenerateNative in tools/gccld/GenerateCode.cpp to pass it.

-Chris