I need to inline a couple of functions during runtime using LLVM. The complication is that such functions are defined in separate bitcode files.
During runtime, I need to generate code for a function such as
void snippet1(); //declaring that snippet1 and 2 are defined in snippet1.c and snippet2.c
void snippet2();
void combo12(){
snippet1();
snippet1();
snippet2();
snippet2();
}
From separate LLVM bitcode files compiled from combo12.c, snippet1.c and snippet2.c. The thing is, I need to inline all calls to snippet1 and snippet2 in combo12. I tried to do this using the following code (main.cpp):
OwningPtr<MemoryBuffer> MB, MB2, MB3;
Module *M1, *M2, *MC12, *MOUT;
LLVMContext Context;
std::string ErrorStr;
MemoryBuffer::getFile("snippet1.bc", MB);
M1 = ParseBitcodeFile(MB.get(), Context);
MemoryBuffer::getFile("snippet2.bc", MB2);
M2 = ParseBitcodeFile(MB2.get(), Context);
MemoryBuffer::getFile("combo12.bc", MB3);
MC12 = ParseBitcodeFile(MB3.get(), Context);
Linker* L;
L = new Linker("testprog", M1, 0);
L->setFlags(llvm::Linker::Verbose);
if (!(L->LinkInModule(M2, &ErrorStr)))
std::cout << ErrorStr;
if (!(L->LinkInModule(MC12, &ErrorStr)))
std::cout << ErrorStr;
MOUT = L->getModule();
MOUT->dump();
PassManager *PM;
PM = new PassManager();
PM->add(createInternalizePass(true));
PM->add(createAlwaysInlinerPass());
if (PM->run(*MOUT)){
std::cout << "\n\n\nCode was altered!\n\n\n" << std::endl;
MOUT->dump();
std::cout << "\n\n ALTERED BEAST \n\n" << std::endl;
}
snippet1.c:
//What this function does is irrelevant
#include "post_opt.h" //contains the struct exstr declaration
extern struct exstr a;
inline void snippet1() __attribute((always_inline));
void snippet1(){
int x, y;
a.b = 10;
x = 2;
if(x < a.a){
y = x + 1;
}
}
I compiled snippet1.c, snippet2.c and combo12.c using
clang -c -emit-llvm snippet1.c -o snippet1.bc -O0
clang -c -emit-llvm snippet2.c -o snippet2.bc -O0
clang -c -emit-llvm combo12.c -o combo12.bc -O0
And main.cpp with
clang++ -g main.cpp `llvm-config --cppflags --ldflags --libs --cppflags --ldflags --libs core jit native linker transformutils ipo bitreader` -O0 -o main
When I run ./main, It does not inline the snippet code, although I explicitly mark the function with the always_inline attribute, and use the AlwaysInline pass. It never prints ALTERED BEAST onscreen.
Why does this happen? I thought that, by linking all modules together and applying an IPO pass (AlwaysInline) this would work out ok.
Thanks for any insight!
Inlining occurs during compilation and not linking and inlining is only available with completly defined function at compilation time. So, it is impossible to inlining function from other files ('cause when compiling a file, other one are ignored). The only solution is to define function in every files which need inline thoses functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With