tl; dr
Run your LLVM pass with Clang automatically using the wrapper script at the end.
What’s this
This post shows how to run your LLVM pass directly using clang without having to generate LLVM bitcode and running opt.
Changes to your pass
Register your pass with for EP callback:
extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "MyPass", LLVM_VERSION_STRING,
[](PassBuilder &PB) {
PB.registerPipelineStartEPCallback
(
[&](llvm::ModulePassManager &mpm, llvm::PassBuilder::OptimizationLevel o) -> void{
mpm.addPass(MyPass());
}
);
}};
}
Build your compiler pass and generate the shared binary (libmypass.so
).
Invoke clang using the following switches:
clang -fexperimental-new-pass-manager -fpass-plugin=path/to/libmypass.so
Wrapper script
But wait, do you have to modify the build system of your $LARGE_PROJECT? No, use this clang wrapper which automatically does this for you:
#!/usr/bin/env python
"""
@brief Wrapper to invoke llvm pass using clang
@author Suyash Mahar <contact@suyashmahar.com>
"""
from os.path import basename
import subprocess
import sys
import os
# Path to the LLVM pass
PASS_SO = '/home/smahar/git/cxlbuf/src/storeinst-pass/build/libstoreinst.so'
# Add any extra flags here. E.g., -Wl,-rpath=...
EXTRA_FLAGS = ['']
def get_bins(llvm_dir):
cxx = os.path.join(llvm_dir, "bin/clang++")
cc = os.path.join(llvm_dir, "bin/clang++")
return cc, cxx
def main(fname):
if 'LLVM_DIR' not in os.environ:
raise RuntimeError("LLVM_DIR env not set.")
llvm_dir = os.environ['LLVM_DIR']
cc, cxx = get_bins(llvm_dir)
target = cc
# Check if invoking for clang or clang++
if fname.endswith('++'):
target = cxx
args = sys.argv[1:]
pass_args = ['-fexperimental-new-pass-manager',
'-fpass-plugin=' + PASS_SO] + EXTRA_FLAGS
ret = subprocess.call([target] + pass_args + args)
exit(ret)
if __name__ == "__main__":
main(basename(sys.argv[0]))
Save this script as wclang
and symlink wclang++
to wclang
:
-rwxrwxr-x 1 smahar smahar 1,2K mars 19 12:03 wclang
lrwxrwxrwx 1 smahar smahar 6 mars 18 15:13 wclang++ -> wclang
And you are good to go:
CC=wclang CXX=wclang++ make