convert a compile-time pass to an lto pass

Hi,

I am trying to convert a compile-time legacy module
pass (so) to a link-time pass. I am using ArchLinux amd64
with LLVM 8.0.0 but looking for a way to support llvm 3.8 up to current.

To keep things simple, i am just counting modules, functions, basic blocks.
For compile time usage I used 'clang -Xclang -load -Xclang mypass.so ...'.
That is working as expected.

In llvm/Transforms/IPO/PassManagerBuilder.h I looked for a suitable value
in enum ExtensionPointTy, but found nothing for running at linking time.

Next I tried to use
clang -flto -fuse-ld=gold -Xclang -load -Xclang mypass.so ...'
but then the pass is also run once per translation unit not once at link time.

Since the linker does not know '-load', I am now using
clang -flto -fuse-ld=gold -Xlinker -plugin -Xlinker mypass.so ...
with the effect that the linker cannot find symbol llvm::ModulePass while loading mypass.so

"/usr/bin/ld.gold" -pie --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o test-instr /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib64/Scrt1.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib64/crti.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/crtbeginS.o -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib64 -L/usr/bin/../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/../../.. -L/usr/bin/../lib -L/lib -L/usr/lib -plugin /usr/bin/../lib/LLVMgold.so -plugin-opt=mcpu=x86-64 -plugin-opt=O3 -plugin ../mypass.so /tmp/test-instr-4f23de.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/crtendS.o /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../lib64/crtn.o
/usr/bin/ld.gold: error: ../mypass.so: could not load plugin library: ../mypass.so: undefined symbol: _ZN4llvm10ModulePassD2Ev
clang-8: error: linker command failed with exit code 1 (use -v to see invocation)

The goal is using ḿodule, function, basic block iterators
like before but just at a global scope.

Any help/hint is appreciated.
Many thanks and best regards, Heiko

Hi,

I am trying to convert a compile-time legacy module
pass (so) to a link-time pass. I am using ArchLinux amd64
with LLVM 8.0.0 but looking for a way to support llvm 3.8 up to current.

To keep things simple, i am just counting modules, functions, basic blocks.
For compile time usage I used ‘clang -Xclang -load -Xclang mypass.so …’.
That is working as expected.

In llvm/Transforms/IPO/PassManagerBuilder.h I looked for a suitable value
in enum ExtensionPointTy, but found nothing for running at linking time.

One has been added a few weeks ago I believe.

Next I tried to use
clang -flto -fuse-ld=gold -Xclang -load -Xclang mypass.so …’
but then the pass is also run once per translation unit not once at link
time.

Since the linker does not know ‘-load’, I am now using
clang -flto -fuse-ld=gold -Xlinker -plugin -Xlinker mypass.so …
with the effect that the linker cannot find symbol llvm::ModulePass
while loading mypass.so

I suspect you can’t do that with gold, you need to instead link your pass into the LLVM LTO plugin for Gold.

LLD may be able to load your pass though, I don’t know it there is a command line flag for this though.