c - 在 LLVM 中内联来自不同文件的代码

标签 c llvm clang

我需要在运行时使用 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 传递。它从不在屏幕上打印 ALTERED BEAST。

为什么会这样?我认为,通过将所有模块链接在一起并应用 IPO 通行证 (AlwaysInline),这样就可以了。

感谢您的任何见解!

最佳答案

内联发生在编译期间而不是链接,并且内联仅适用于编译时完全定义的函数。因此,不可能从其他文件内联函数(因为在编译文件时,其他文件会被忽略)。唯一的解决方案是在每个需要内联这些函数的文件中定义函数。

关于c - 在 LLVM 中内联来自不同文件的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10568212/

相关文章:

c - 为什么 sum1 = 46 而 sum2 = 48

cmake - 是否可以使用 gold 链接器编译和链接 Clang/LLVM?

c++ - IR LLVM 形式与汇编

c++ - 在macOS上编译gpsim会导致 “error: ' long long type-name'无效”

c++ - sscanf 中 uint16_t 的正确且可移植的 (Clang/GCC) 修饰符是什么?

c - C语言的头文件和面向对象编程的可重用性?

c - 无法在 ubuntu 18.04.01 上安装 gcc

c - Typedef,违反 ODR : same keyword alias different types

c++ - 可以使用 clang 将 C++17 与 CUDA 一起使用吗?

c++ - 如何在没有-g的情况下获取元数据