Source built LLVM's opt does not load passes

Hello,

I have built llvm-13 from source from the github repo branch release/13.x. The pass shown in the tutorial works with the system’s opt but not with the opt that is built from source.

Is there a flag we should pass when building llvm from source to enable loading custom passes?

Both the versions are 13.0.1

There is indeed a flag,

-DLLVM_ENABLE_PLUGINS=ON 

did you try that one?

When I use this flag to build LLVM and later use it to compile my plugin, it throws an error.

opt: CommandLine Error: Option 'use-dbg-addr' registered more than once!

When I add the flag BUILD_SHARED_LIBS=ON and compile llvm, I am not able to build the plugin anymore. It seems like I am not able to link to llvm using libLLVM.dylib formed anymore.

What is the error and the invocation command used?

For compiling llvm the following cmake command and then make in build directory

cmake -S llvm -B build -DLLVM_BUILD_LLVM_DYLIB=1 -DLLVM_ENABLE_PROJECTS='clang' -DLLVM_ENABLE_PLUGINS=ON

for compiling the plugin I have this cmake file:

project(passes)

cmake_minimum_required(VERSION 3.22)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_C_COMPILER "~/compiler/llvm-project/build/bin/clang")
set(CMAKE_CXX_COMPILER "~/compiler/llvm-project/build/bin/clang++")
set(LLVM_DIR "~/compiler/llvm-project/build/lib/cmake/llvm")
find_package(LLVM)
add_definitions(${LLVM_DEFINITIONS})
include_directories(${LLVM_INCLUDE_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})

include_directories(./include)

add_library(passes MODULE
    ./src/hello_world.cpp
)

set_target_properties(passes PROPERTIES 
    COMPILE_FLAGS "-fno-exceptions -fno-rtti -fPIC -g"
)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-exceptions -fno-rtti -fPIC -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti -fPIC -g -lLLVM")

the plugin compiles using cmake properly.

But after compiling using the clang built from source and using the following command

$(OPT) -load $(SO_PATH) $(pass) $(name).ll -o $(name)_.ll -enable-new-pm=0 -S

throws opt: CommandLine Error: Option 'use-dbg-addr' registered more than once!

Further on building llvm using

cmake -S llvm -B build -DLLVM_BUILD_LLVM_DYLIB=1 -DLLVM_ENABLE_PROJECTS='clang' -DLLVM_ENABLE_PLUGINS=ON -DBUILD_SHARED_LIBS=ON

on compiling the plugin I get

o
Undefined symbols for architecture arm64:
  "llvm::raw_ostream::write_escaped(llvm::StringRef, bool)", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in hello-world.cpp.o
  "llvm::raw_ostream::write(char const*, unsigned long)", referenced from:
      llvm::raw_ostream::operator<<(llvm::StringRef) in hello-world.cpp.o
  "llvm::raw_ostream::write(unsigned char)", referenced from:
      llvm::raw_ostream::operator<<(char) in hello-world.cpp.o
  "llvm::FunctionPass::assignPassManager(llvm::PMStack&, llvm::PassManagerType)", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::PassRegistry::registerPass(llvm::PassInfo const&, bool)", referenced from:
      llvm::RegisterPass<(anonymous namespace)::Hello>::RegisterPass(llvm::StringRef, llvm::StringRef, bool, bool) in hello-world.cpp.o
  "llvm::PassRegistry::getPassRegistry()", referenced from:
      llvm::RegisterPass<(anonymous namespace)::Hello>::RegisterPass(llvm::StringRef, llvm::StringRef, bool, bool) in hello-world.cpp.o
  "llvm::EnableABIBreakingChecks", referenced from:
      llvm::VerifyEnableABIBreakingChecks in hello-world.cpp.o
  "llvm::Pass::releaseMemory()", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::dumpPassStructure(unsigned int)", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::getAsImmutablePass()", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::getAsPMDataManager()", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::preparePassManager(llvm::PMStack&)", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::getAdjustedAnalysisPointer(void const*)", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::~Pass()", referenced from:
      llvm::FunctionPass::~FunctionPass() in hello-world.cpp.o
  "llvm::errs()", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in hello-world.cpp.o
  "llvm::FunctionPass::createPrinterPass(llvm::raw_ostream&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::FunctionPass::getPotentialPassManagerType() const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::getPassName() const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::verifyAnalysis() const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::getAnalysisUsage(llvm::AnalysisUsage&) const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Pass::print(llvm::raw_ostream&, llvm::Module const*) const", referenced from:
      vtable for (anonymous namespace)::Hello in hello-world.cpp.o
  "llvm::Value::getName() const", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in hello-world.cpp.o
  "vtable for llvm::FunctionPass", referenced from:
      llvm::FunctionPass::FunctionPass(char&) in hello-world.cpp.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for llvm::Pass", referenced from:
      llvm::Pass::Pass(llvm::PassKind, char&) in hello-world.cpp.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture arm64
clang-13: error: linker command failed with exit code 1 (use -v to see invocation)

I understand it is not able to link to the components so I add all the linker flags to the cmake and then it gives the same error when trying to load the plugin as before.