我知道如何从LLVM位代码图像解析模块,以及如何遍历函数定义。
现在,我想对功能进行重新排序以改善某些功能之间的局部性,这些功能被测量为彼此之间具有更紧密的关系。
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/CFG.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_ostream.h>
using namespace llvm;
constexpr const char TEST_FILE[] = "some-file";
std::vector<std::string> symbol_order {};
int some_function() {
auto context = LLVMContext{};
SMDiagnostic err;
auto module = parseIRFile(TEST_FILE, err, context);
// get all functions and adjust order according to symbol order
// wrtie back to a valid module bitcode file
}
事实证明这很困难,因为我可能需要关闭该函数并按顺序插入它们,这超出了我目前的知识。
在我真的把自己变成这个问题之前,我还有更多的担忧:
IR文件中定义的顺序会有效影响最终ELF输出吗?
我目前正在编写一个直接在IR文件上运行的可执行文件;写模块通行证会更合适吗?
我看到对函数进行排序的一种可能方法是:
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/CFG.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_ostream.h>
#include <absl/container/flat_hash_map.h>
using namespace llvm;
constexpr const char TEST_FILE[] = "file.bc";
absl::flat_hash_map<std::string, size_t> order;
struct Compare {
bool operator()(const Function& a, const Function& b) {
return order[a.getName().data()] < order[b.getName().data()];
}
};
int main() {
auto context = LLVMContext{};
SMDiagnostic err;
auto module = parseIRFile(TEST_FILE, err, context);
auto& list = module->getFunctionList();
list.sort(Compare());
WriteBitcodeToFile(*module, llvm::outs());
// get all functions and adjust order according to symbol order
// wrtie back to a valid module bitcode file
}
会破坏某些依赖关系吗?
IR中的功能顺序通常不定义最终二进制文件中的功能顺序。甚至,链接器可以根据需要自由地对功能进行重新排序。通常,链接器的工作是改善功能的局部性。 LLD已经为此提供了一些代码。