首页 > 解决方案 > LLVM C++ API 位码加载和执行

问题描述

我正在寻找一个完整的示例,涵盖 LLVM C++ API 的使用,特别是从位码(不是拼写错误,他们称之为位码)文件中加载一个函数,运行它并获得结果。我研究了这篇博文,并试图将其移植到 C++,但我很难理解如何创建所需的各种实例,尤其是执行引擎。我正在使用clang -c -emit-llvm file.c将 C 文件编译为.bcLLVM 位码文件。该命令clang -S -emit-llvm file.c也可以工作并生成一个文本.ll文件。该功能parseIRFile似乎能够同时加载两者。

这是我到目前为止所拥有的:

LLVMContext context;
SMDiagnostic error;
unique_ptr<Module> mod = parseIRFile(StringRef(pathToLlOrBcFile), error, context);

我不必使用 JIT,我现在可以使用基本解释器;但我希望让它与 MCJIT 或以后调用的任何东西一起工作。

感谢@arnt 注意到我实际上使用的是 IR 文本格式;我更改了 Makefile 和 C++ 应用程序以反映 .ll 和 .bc 都可以由同一个函数解析的事实。

标签: llvmllvm-c++-api

解决方案


llvm-devel.x86_64 9.0.1-5.fc31在 Fedora 31 上使用。下面的完整代码。

main.cc(这是加载 LLVM 位码的 C++ 应用程序)

#include <iostream>

#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/GenericValue.h>

using std::unique_ptr;
using std::cout;
using std::endl;

using llvm::Module;
using llvm::SMDiagnostic;
using llvm::LLVMContext;
using llvm::parseIRFile;
using llvm::StringRef;
using llvm::ExecutionEngine;
using llvm::EngineBuilder;
using llvm::ArrayRef;
using llvm::GenericValue;
using llvm::Function;

int main(int argc, char const *argv[]) {
  LLVMContext context;
  SMDiagnostic error;
  unique_ptr<Module> mod = parseIRFile(StringRef("hosted.bc" /* .ll files also work */), error, context);
  ExecutionEngine *executionEngine = EngineBuilder(std::move(mod)).setEngineKind(llvm::EngineKind::Interpreter).create();
  Function *add = executionEngine->FindFunctionNamed(StringRef("add"));
  GenericValue param1, param2;
  param1.FloatVal = 5.5;
  param2.FloatVal = 2.7;
  GenericValue params[] = { param1, param2 };
  ArrayRef<GenericValue> args = ArrayRef<GenericValue>(params, 2);
  GenericValue result = executionEngine->runFunction(add, args);
  cout << param1.FloatVal << " + " << param2.FloatVal << " = " << result.FloatVal << endl;
}

hosts.c(这是一个 C 应用程序,我用 编译成一个.bc文件clang

float add(float a, float b) {
  return a + b;
}

Makefile(用于编译本机应用程序和要在其中托管的 LLVM 字节码)

app.o: main.cc
    g++ main.cc -lLLVM -o app.o

hosted.bc: hosted.c
    clang -c -emit-llvm hosted.c

clean:
    rm app.o
    rm hosted.bc

.PHONY: clean

输出(编译和运行)

[dario@localhost llvm-cpp-first]$ make hosted.bc && make && ./app.o 
clang -c -emit-llvm hosted.c
g++ main.cc -lLLVM -o app.o
5.5 + 2.7 = 8.2

推荐阅读