Reputation: 79
I am trying to create an LLVM Pass with two source files, but when I compile, cmake yells at me with:
[1/1] Linking CXX shared module lib/LLVMHydrogen.so
FAILED: : && /usr/bin/c++ -fPIC -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor -Wno-comment -std=c++11 -fPIC -g -shared -Wl,-soname,LLVMHydrogen.so -o lib/LLVMHydrogen.so lib/Transforms/Hydrogen/CMakeFiles/LLVMHydrogen.dir/Hydrogen.cpp.o lib/Transforms/Hydrogen/CMakeFiles/LLVMHydrogen.dir/conditional_blocks.cpp.o -Wl,-rpath,"\$ORIGIN/../lib" && :
/usr/bin/ld: lib/Transforms/Hydrogen/CMakeFiles/LLVMHydrogen.dir/conditional_blocks.cpp.o: relocation R_X86_64_PC32 against undefined symbol `_ZTVN12_GLOBAL__N_18HydrogenE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
The key point being:
relocation R_X86_64_PC32 against undefined symbol `_ZTVN12_GLOBAL__N_18HydrogenE' can not be used when making a shared object; recompile with -fPIC
I tried add -fPIC to my compilation flags (and link flags for good measure), but nothing helped. This is my CMakeLists.txt:
SET(COMPILE_FLAGS "-fPIC")
SET(LINK_FLAGS "-lPIC")
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINK_FLAGS}" )
add_llvm_loadable_module( LLVMHydrogen
Hydrogen.cpp
conditional_blocks.cpp
DEPENDS
intrinsics_gen
)
But I get the same output. What am I doing wrong? I feel using multiple source files should be exceedingly simple :/
Thanks
Source code:
hydrogen.h:
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
using namespace std;
using namespace llvm;
namespace {
struct Hydrogen : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
Hydrogen() : FunctionPass(ID) {}
bool runOnFunction(Function &f) override;
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
}
static const char h_name[] = "Hydrogen pass";
char Hydrogen::ID = 0;
static RegisterPass<Hydrogen> X("Hydrogen", "Hydrogen Pass");
hydrogen.cpp: (The first 'main' file)
#include "hydrogen.h"
bool Hydrogen::runOnFunction(Function &fun)
{
return true;
}
conditional_blocks.cpp: (The second file)
#include "hydrogen.h"
Upvotes: 2
Views: 1044
Reputation: 79
Changing the code into the following fixed the problem. I believe it was the addition of the "virtual" keywords in the header, along with the inclusion of "virtual ~Hydrogen() { }"
Working source with multiple LLVM source files:
Same CMakeLists.txt as posted in question.
hydrogen.h:
#include ....
using namespace std;
using namespace llvm;
struct Hydrogen : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
Hydrogen() : FunctionPass(ID) {}
virtual ~Hydrogen() { }
virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
virtual bool runOnFunction(Function &f) override;
};
hydrogen.cpp:
#include "hydrogen.h"
using namespace hydrogen_ns;
static const char h_name[] = "Hydrogen pass";
char Hydrogen::ID = 0;
static RegisterPass<Hydrogen> X("Hydrogen", "Hydrogen Pass");
bool Hydrogen::runOnFunction(Function &fun)
{
return true;
}
conditional_blocks.cpp:
#include "hydrogen.h"
Upvotes: 1