Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inlining code from distinct files in LLVM

Tags:

c

llvm

clang

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!

like image 256
Juliano Foleiss Avatar asked May 29 '26 23:05

Juliano Foleiss


1 Answers

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.

like image 51
Garf365 Avatar answered May 31 '26 13:05

Garf365