-O4 -fvisibility=hidden

After trying the recommended use of -O4 -fvisibility=hidden to
compile xplor-nih with full LTO optimizations, I discovered three
symbols become undefined...

llvm-gcc-4 -O4 -fvisibility=hidden -o xplor xplor.o \
     \
    -L. -lxplorCmd -lxplor -L/Users/howarth/xplor-nih-2.21/bin.Darwin_9_x86/ -lfft -lintVar -lvmd -lpy -lswigpy-xplor -ltclXplor -lswigtcl8-xplor -lnmrPot -lcommon -lmarvin \
       -lcrypto -L/sw/lib/llvm-gcc-4.2/lib -lgfortran -llapack -lblas -L/Users/howarth/xplor-nih-2.21/bin.Darwin_9_x86/ \
     
Undefined symbols:
  "_xplorwrapproc_slave_", referenced from:
      llvm bitcode in xplor.o
  "_python_interp_", referenced from:
      llvm bitcode in xplor.o
  "_tcl_interp_", referenced from:
      llvm bitcode in xplor.o
ld: symbol(s) not found

These are all defined as extern as follows...

extern "C" void
FORTRAN(tcl_interp) (const long& canReturn,
                             long& qterm,
                             long& fd)

extern "C" void
FORTRAN(python_init)(const long& argc,
                           char** argv)

extern "C" void FORTRAN(xplorwrapproc_slave)();

The only symbols that become undefined are those extern
symbols which calling fortran routines from c++ code.
I'll look into creating a testcase and opening a PR for
this issue.
               Jack

  After trying the recommended use of -O4 -fvisibility=hidden to
compile xplor-nih with full LTO optimizations, I discovered three
symbols become undefined...

llvm-gcc-4 -O4 -fvisibility=hidden -o xplor xplor.o \
     \
    -L. -lxplorCmd -lxplor -L/Users/howarth/xplor-nih-2.21/bin.Darwin_9_x86/ -lfft -lintVar -lvmd -lpy -lswigpy-xplor -ltclXplor -lswigtcl8-xplor -lnmrPot -lcommon -lmarvin \
       -lcrypto -L/sw/lib/llvm-gcc-4.2/lib -lgfortran -llapack -lblas -L/Users/howarth/xplor-nih-2.21/bin.Darwin_9_x86/ \
  
Undefined symbols:
"_xplorwrapproc_slave_", referenced from:
     llvm bitcode in xplor.o
"_python_interp_", referenced from:
     llvm bitcode in xplor.o
"_tcl_interp_", referenced from:
     llvm bitcode in xplor.o
ld: symbol(s) not found

These are all defined as extern as follows...

extern "C" void
FORTRAN(tcl_interp) (const long& canReturn,
                            long& qterm,
                            long& fd)

extern "C" void
FORTRAN(python_init)(const long& argc,
                          char** argv)

extern "C" void FORTRAN(xplorwrapproc_slave)();

defining them as extern is not enough to mark them as "exported".

You should use the visibility attribute.

extern "C" void FORTRAN(xplorwrapproc_slave)() __attribute__((visibility("default")));

Jean-Daniel,
    Doing that changes the error messages into a bus
error on the darwin linker. I'll try using -fvisibility=
hidden first with current gcc trunk's compilers and come
back to llvm-gcc4.2 later. I noticed that there are
known issues with using -fvisibility with fortran...

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35827

I have removed all of the -fvisibility=hidden flags
from the gfortran compiles but wonder if this is still
an issue since the fortran calls are being accessed
from c++ files with the -fvisibility=hidden flag in
use. Perhaps PR35827 also includes fortran calls in
c++ not understanding the use of -fvisibility as
well as fortran code itself.
                   Jack

Hi Jack,

   Doing that changes the error messages into a bus
error on the darwin linker.

Pl. file bugzilla report (or radar) with a reproducible test case so that we can investigate this linker crash.

As you know, one way to control symbol visibility is to use gcc's (inherited by llvm-gcc) visibility support. GCC supports, 1) command line options 2) attributes and 3) pragmas in this regard. Following document provides good summary...

http://developer.apple.com/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html#//apple_ref/doc/uid/TP40001670

Another way to control symbol visibility is to use linker's interface. See ld man page for more info on -exported_symbols_list, -exported_symbols, -unexported_symbols_list etc.. flags. If you're going to try this approach, pl. read ld man page first.

Devang,
   I was surprised to discover that I could build all of
pymol with -fvisibility=hidden using gcc 4.4 or
llvm-gcc-4.2 with only a single header change...

--- pymol-1.1/layer4/Cmd.h.orig 2009-01-30 18:58:58.000000000 -0500
+++ pymol-1.1/layer4/Cmd.h 2009-01-30 19:00:17.000000000 -0500
@@ -18,7 +18,8 @@

#include"os_python.h"

-void init_cmd(void);
+void init_cmd(void)
+__attribute__((visibility("default")));

extern PyObject *PM_Globals;

One of the advantages of running as a python module I guess. I was
also able to build pymol with -O4 using the llvm 2.5 libLTO.dylib
so that full Link Time Optimizations were performed. Everything
compiled and linked fine. The resulting pymol runs its demos without
regressions. Nice.
             Jack

I was able to also build sparky (Sparky - NMR Assignment Program)
at -O4 under llvm-gcc-4.2 and llvm-g++-4.2 on darwin with minor patches...

--- sparky/c++/_tkinter.c.orig 2009-01-30 22:14:28.000000000 -0500
+++ sparky/c++/_tkinter.c 2009-01-30 22:16:40.000000000 -0500
@@ -3089,6 +3089,9 @@
        }
}

+PyMODINIT_FUNC
+init_tkinter(void)
+__attribute__((visibility("default")));

PyMODINIT_FUNC
init_tkinter(void)
--- sparky/c++/python.cc.orig 2009-01-30 22:23:07.000000000 -0500
+++ sparky/c++/python.cc 2009-01-30 22:23:36.000000000 -0500
@@ -3566,6 +3566,9 @@
// Initialization routine called by python when module is dynamically loaded.
//
extern "C" void initspy()
+__attribute__((visibility("default")));

Tk/Python driven software appears very friendly to -fvisibility=hidden.

Nice!

Are there any particular optimization options that one should use besides
-O4 -fvisibility=hidden to enable all of the possible llvm Link Time Optimizations?

Nope, that should be enough. "-O4" is effectively -O3 + -flto. You might also try -O2 -flto explicitly if you care about code size.

Also, I assume that one only needs to compile the object files with
-O4 -fvisibility=hidden and that the actual linkage doesn't need those
flags to enable full LTO, correct?

Right.

Is there a significant code size or perf difference with lto?

-Chris