3

LLVMを使用して、実行時にいくつかの関数をインライン化する必要があります。複雑なのは、そのような関数が別々のビットコードファイルで定義されていることです。

実行時に、次のような関数のコードを生成する必要があります

void snippet1();         //declaring that snippet1 and 2 are defined in snippet1.c and snippet2.c
void snippet2();

void combo12(){
    snippet1();
    snippet1();
    snippet2();
    snippet2();
}

combo12.c、snippet1.c、およびsnippet2.cからコンパイルされた個別のLLVMビットコードファイルから。重要なのは、combo12のsnippet1とsnippet2へのすべての呼び出しをインライン化する必要があるということです。次のコード(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;
    }
}

snippet1.c、snippet2.c、combo12.cを使用してコンパイルしました

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

そしてmain.cppと

clang++ -g main.cpp `llvm-config --cppflags --ldflags --libs --cppflags --ldflags --libs core jit native linker transformutils ipo bitreader` -O0 -o main

./mainを実行すると、関数にalways_inline属性を明示的にマークし、AlwaysInlineパスを使用しますが、スニペットコードはインライン化されません。獣王記を画面に印刷することはありません。

なぜこれが起こるのですか?すべてのモジュールをリンクし、IPOパス(AlwaysInline)を適用することで、問題なく機能すると思いました。

洞察をありがとう!

4

1 に答える 1

2

インライン化はコンパイル中に発生し、リンクは発生しません。インライン化は、コンパイル時に完全に定義された関数でのみ使用できます。したがって、他のファイルから関数をインライン化することはできません('ファイルをコンパイルするときに、他のファイルは無視されるため)。唯一の解決策は、それらの関数をインライン化する必要があるすべてのファイルで関数を定義することです。

于 2015-03-03T08:05:38.100 に答える