llvm-gfortran problems

Hello,

I have been trying to compile a few small programs [http://www.esm.psu.edu/~ajm138/fortranexamples.html] using llvm-gfortran. Since I run my own pass on the generated bitcode, I have had to split the compilation process into using llvm-gfortran, opt and then llvm-ld (for linking, as I do with C/C++ programs). For now, I’ll drop the `opt’ statement. Here’s what I see while compiling:

$ llvm-gfortran -c sample.f -emit-llvm -o sample.o

$ lli sample.o
‘main’ function not found in module

$ llvm-dis < sample.o | grep main | wc -l
0

$ llvm-dis < sample.o | grep MAIN | wc -l
1

$ llvm-ld -native sample.o -L ~/apps/llvm-gcc/lib64/ -lgfortran

/usr/lib/…/lib64/crt1.o: In function _start': (.text+0x21): undefined reference to main’
collect2: ld returned 1 exit status
llvm-ld:

I am not very familiar with Fortran programs. I saw a few programs that had a “MAIN” subroutine defined, some others that did not. Am I missing something while compiling the code? Is there a different way to compile bitcode (from Fortran programs) to a native binary?

Thanks,
Ashay

Hi Ashay,

Do you need specifically llvm-gfortran that is based on gcc 4.2? Since
that, DragonEgg has been introduced - a powerful plugin to gcc that
makes it possible to utilize regular gcc compilers as frontends to
llvm: http://dragonegg.llvm.org/

It generates Fortran90 programs for me very well.

- D.

I successfully compiled your first sample program:

[marcusmae@zacate recursive]$ make
dragonegg-gfortran -fplugin=/opt/kgen/lib64/dragonegg.so
-fplugin-arg-dragonegg-emit-ir -emit-llvm -S recursive.f -o
recursive.bc
llc -march=x86-64 recursive.bc -o recursive.s
gfortran recursive.s -o recursive
[marcusmae@zacate recursive]$ ./recursive
Enter number of repeats
10
x = 1
x = 2
x = 3
x = 4
x = 5
x = 6
x = 7
x = 8
x = 9
x = 10

Everything is in attached archive.

- D.

recursive.tar.gz (6.17 KB)

Hello

I am not very familiar with Fortran programs. I saw a few programs that had
a "MAIN" subroutine defined, some others that did not. Am I missing
something while compiling the code? Is there a different way to compile
bitcode (from Fortran programs) to a native binary?

For Fortran MAIN is indeed something similar to C main, but not
exactly the same.
You have to link the runtime library (libgfortran.a) in order to get
"proper" main, mak sure all stuff is initialized properly, etc.

Hello,

Sorry for the late reply. Using dragonegg worked well, thanks all!

Just as a note… I had to use llvm-ld during the link step because gfortran could not link bitcode. Here’s an example of the error shown when using gfortran instead of llvm-ld:

$ ${GCC_4_5_0}/bin/gfortran hw.f -c -fplugin=${DRAGONEGG_PLUGIN}/dragonegg.so -o hw.o -flto -emit-llvm -S
$ ${LLVM_2_9}/bin/opt -mem2reg hw.o -o hw.o
$ ${GCC_4_5_0}/bin/gfortran -fplugin=${DRAGONEGG_PLUGIN}/dragonegg.so ${GCC_4_5_0}/lib64/libgfortran.a hw.o -o hw

hw.o: file not recognized: File format not recognized
collect2: ld returned 1 exit status

$ file hw.o
hw.o: data

Instead, using llvm-ld:
$ ${LLVM_2_9}/bin/llvm-ld -native hw.o -o hw ${GCC_4_5_0}/lib64/libgfortran.a -lm

llvm-gcc had the gold plugin. I wonder if there is any equivalent of that for dragonegg to be able to compile bitcode and native object code in a transparent manner.

Thanks again!
Ashay

Ashay,

If I understand correctly, in hw.o you would have llvm bytecode, while
linker expects regular object binary. Probably first you need to emit
asm out of bytecode using llc?

- D.

Thats correct. But using llc becomes a problem when I have archives (.a files). I could, in theory, extract its contents to a tempdir and then use llc and link but just wondering if there is a more elegant solution.

Ashay

Sorry, at what step do you need archive? llc emits binary, it does not
perform any linking, thus it does not need anything except the input
bytecode file. Then during linking you can link whatever archives of
binaries you want.

Hmm… I didn’t explain the problem completely last time. I am creating a drop-in replacement for gcc and gfortran that runs an additional pass on the bitcode before generating the native binary. Here’s whats happening: If the source code compilation process builds a static library (.a archive file), I need a means to link the `.a’ file statically into the application. So if the original statement was:

gfortran file.o -L somedir -lmylib -o file

then my modified compilation process would have to deal with file.o and libmylib.a to generate the binary `file’. Now, all files essentially contain bitcode (file.o and object files inside libmylib.a). So the pseudo-code would look like:

– QUOTE –

For all input files passed to compiler:
If extension is .o:
Use llc to generate .s file
Add this filename to some collection
Else if extension is .a:
Extract contents of this archive
Use llc on each file to generate .s file
Add each filename to the collection
End if
End for

Retrieve all `.s’ filenames and pass them all to gcc or gfortran

– UNQUOTE –

But the part that deals with `.a’ files is a bit ugly. llvm-ld handles the archive (.a) files without any manual extraction but I fear that because llvm-ld is not a full-featured linker, I might run into a wall because of incompatible options between gfortran/gcc and llvm-ld.

Ashay

I see. And what's the purpose for outputting bitcode into *.o and *.a
files? Do you want to perform an LLVM pass on linking step?

No, I am running the LLVM pass at the compilation step. So by the time I reach the link step, the transformed bitcode has been generated.

Ashay

If all llvm passes are compile-time, then I think nothing limits you
from invoking llc for each standalone object: source -> bitcode ->
binary object. And binary objects will be generated before packing
them into static libraries. I don't see any problem.

Hi Ashay,

Sorry for the late reply. Using dragonegg worked well, thanks all!

Just as a note... I had to use llvm-ld during the link step because
gfortran could not link bitcode. Here's an example of the error shown
when using gfortran instead of llvm-ld:

$ ${GCC_4_5_0}/bin/gfortran hw.f -c -fplugin=
${DRAGONEGG_PLUGIN}/dragonegg.so -o hw.o -flto -emit-llvm -S
$ ${LLVM_2_9}/bin/opt -mem2reg hw.o -o hw.o
$ ${GCC_4_5_0}/bin/gfortran
-fplugin=${DRAGONEGG_PLUGIN}/dragonegg.so ${GCC_4_5_0}/lib64/libgfortran.a
hw.o -o hw
hw.o: file not recognized: File format not recognized
collect2: ld returned 1 exit status

$ file hw.o
hw.o: data

Instead, using llvm-ld:
$ ${LLVM_2_9}/bin/llvm-ld -native hw.o -o hw
${GCC_4_5_0}/lib64/libgfortran.a -lm

llvm-gcc had the gold plugin. I wonder if there is any equivalent of
that for dragonegg to be able to compile bitcode and native object code
in a transparent manner.

can you please open a bug report about this. Hopefully there is a
straightforward way to use the gold plugin with dragonegg, but I never
thought about it (I always do LLVM LTO "by hand").

Ciao, Duncan.