I'm trying to make a simple LLVM pass but I can't compile the pass code.
Pass is located outside the LLVM source tree, which is already supported by LLVM.
Here is my Project's CMakeLists.txt:
cmake_minimum_required(VERSION 3.25)
project(LLVM1Proj)
# Set flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
# Include LLVM library
find_package(LLVM REQUIRED CONFIG)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(AddLLVM)
# Enable isolated passes
set(LLVM_ENABLE_PLUGINS ON)
separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
add_definitions(${LLVM_DEFINITIONS_LIST})
include_directories(${LLVM_INCLUDE_DIRS})
add_subdirectory("easypass")
add_executable(LLVM1 "main.cpp")
llvm_map_components_to_libnames(llvm_libs support core irreader)
target_link_libraries(LLVM1 ${llvm_libs})
And, "easypass/CMakeLists.txt":
add_llvm_library(easypass MODULE
easypass.cpp
PLUGIN_TOOL
opt
)
My project's main.cpp file only contains the entry point.
And my easypass.cpp file:
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
namespace {
class Easy : public llvm::FunctionPass {
public:
static char ID;
Easy() : FunctionPass(ID) {}
bool runOnFunction(llvm::Function &F) override {
llvm::errs() << "Hello: ";
llvm::errs().write_escaped(F.getName()) << '\n';
return false;
}
};
}
char Easy::ID = 0;
static llvm::RegisterPass<Easy> X("Easy", "Easy pass", false);
static llvm::RegisterStandardPasses Y(
llvm::PassManagerBuilder::EP_EarlyAsPossible,
[](const llvm::PassManagerBuilder &Builder,
llvm::legacy::PassManagerBase &PM) { PM.add(new Easy()); });
CMake prepares the compile command for CLang as:
cmd.exe /C "cd . && C:\PROGRA~1\MICROS~1\2022\COMMUN~1\VC\Tools\Llvm\x64\bin\clang.exe -fuse-ld=lld-link -nostartfiles -nostdlib -std=c++17 -O0 -g -Xclang -gcodeview -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd -g -Xclang -gcodeview -Wl,--gc-sections -shared -o easypass\easypass.dll -Xlinker /MANIFEST:EMBED -Xlinker /implib:easypass\easypass.lib -Xlinker /pdb:easypass\easypass.pdb -Xlinker /version:0.0 easypass/CMakeFiles/easypass.dir/easypass.cpp.obj -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames && cd ."
And I get those errors when trying to compile it using CLang:
[build] lld-link: warning: ignoring unknown argument '--gc-sections'
[build] lld-link: error: undefined symbol: public: static class llvm::PassRegistry * __cdecl llvm::PassRegistry::getPassRegistry(void)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\PassSupport.h:101
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: __cdecl llvm::RegisterPass<class `anonymous namespace'::Easy>::RegisterPass<class `anonymous namespace'::Easy>(class llvm::StringRef, class llvm::StringRef, bool, bool))
[build]
[build] lld-link: error: undefined symbol: public: void __cdecl llvm::PassRegistry::registerPass(class llvm::PassInfo const &, bool)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\PassSupport.h:101
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: __cdecl llvm::RegisterPass<class `anonymous namespace'::Easy>::RegisterPass<class `anonymous namespace'::Easy>(class llvm::StringRef, class llvm::StringRef, bool, bool))
[build]
[build] lld-link: error: undefined symbol: public: static int __cdecl llvm::PassManagerBuilder::addGlobalExtension(enum llvm::PassManagerBuilder::ExtensionPointTy, class std::function<void __cdecl(class llvm::PassManagerBuilder const &, class llvm::legacy::PassManagerBase &)>)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\Transforms\IPO\PassManagerBuilder.h:221
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: __cdecl llvm::RegisterStandardPasses::RegisterStandardPasses(enum llvm::PassManagerBuilder::ExtensionPointTy, class std::function<void __cdecl(class llvm::PassManagerBuilder const &, class llvm::legacy::PassManagerBase &)>))
[build]
[build] lld-link: error: undefined symbol: public: static void __cdecl llvm::PassManagerBuilder::removeGlobalExtension(int)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\Transforms\IPO\PassManagerBuilder.h:228
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: __cdecl llvm::RegisterStandardPasses::~RegisterStandardPasses(void))
[build]
[build] lld-link: error: undefined symbol: class llvm::raw_fd_ostream & __cdecl llvm::errs(void)
[build] >>> referenced by C:\Development\Projects\LLVM1\easypass\easypass.cpp:19
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: virtual bool __cdecl `anonymous namespace'::Easy::runOnFunction(class llvm::Function &))
[build] >>> referenced by C:\Development\Projects\LLVM1\easypass\easypass.cpp:20
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: virtual bool __cdecl `anonymous namespace'::Easy::runOnFunction(class llvm::Function &))
[build]
[build] lld-link: error: undefined symbol: public: class llvm::StringRef __cdecl llvm::Value::getName(void) const
[build] >>> referenced by C:\Development\Projects\LLVM1\easypass\easypass.cpp:20
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: virtual bool __cdecl `anonymous namespace'::Easy::runOnFunction(class llvm::Function &))
[build]
[build] lld-link: error: undefined symbol: public: class llvm::raw_ostream & __cdecl llvm::raw_ostream::write_escaped(class llvm::StringRef, bool)
[build] >>> referenced by C:\Development\Projects\LLVM1\easypass\easypass.cpp:20
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: virtual bool __cdecl `anonymous namespace'::Easy::runOnFunction(class llvm::Function &))
[build]
[build] lld-link: error: undefined symbol: public: virtual __cdecl llvm::Pass::~Pass(void)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\Pass.h:308
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: virtual __cdecl llvm::FunctionPass::~FunctionPass(void))
[build]
[build] lld-link: error: undefined symbol: public: class llvm::raw_ostream & __cdecl llvm::raw_ostream::write(unsigned char)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\Support\raw_ostream.h:192
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: class llvm::raw_ostream & __cdecl llvm::raw_ostream::operator<<(char))
[build]
[build] lld-link: error: undefined symbol: public: class llvm::raw_ostream & __cdecl llvm::raw_ostream::write(char const *, unsigned __int64)
[build] >>> referenced by C:\Program Files (x86)\LLVM\include\llvm\Support\raw_ostream.h:217
[build] >>> easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(public: class llvm::raw_ostream & __cdecl llvm::raw_ostream::operator<<(class llvm::StringRef))
[build]
[build] lld-link: error: undefined symbol: public: virtual class llvm::StringRef __cdecl llvm::Pass::getPassName(void) const
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void __cdecl llvm::Pass::print(class llvm::raw_ostream &, class llvm::Module const *) const
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual class llvm::Pass * __cdecl llvm::FunctionPass::createPrinterPass(class llvm::raw_ostream &, class std::basic_string<char, struct std::char_traits<char>, class std::allocator<char>> const &) const
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void __cdecl llvm::FunctionPass::assignPassManager(class llvm::PMStack &, enum llvm::PassManagerType)
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void __cdecl llvm::Pass::preparePassManager(class llvm::PMStack &)
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual enum llvm::PassManagerType __cdecl llvm::FunctionPass::getPotentialPassManagerType(void) const
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void __cdecl llvm::Pass::getAnalysisUsage(class llvm::AnalysisUsage &) const
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void __cdecl llvm::Pass::releaseMemory(void)
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual void * __cdecl llvm::Pass::getAdjustedAnalysisPointer(void const *)
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: undefined symbol: public: virtual class llvm::ImmutablePass * __cdecl llvm::Pass::getAsImmutablePass(void)
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const `anonymous namespace'::Easy::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::FunctionPass::`vftable')
[build] >>> referenced by easypass/CMakeFiles/easypass.dir/easypass.cpp.obj:(const llvm::Pass::`vftable')
[build]
[build] lld-link: error: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
[build] clang: error: linker command failed with exit code 1
I don't know what I'm missing. I'm reading LLVM's documentation but I think it doesn't include all we may need. I faced lots of issues when compiling it as what "exactly" their documentation says. What I'm doing wrong here?