llvm - LLVM C++ API 位码加载和执行
问题描述
我正在寻找一个完整的示例,涵盖 LLVM C++ API 的使用,特别是从位码(不是拼写错误,他们称之为位码)文件中加载一个函数,运行它并获得结果。我研究了这篇博文,并试图将其移植到 C++,但我很难理解如何创建所需的各种实例,尤其是执行引擎。我正在使用clang -c -emit-llvm file.c
将 C 文件编译为.bc
LLVM 位码文件。该命令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 都可以由同一个函数解析的事实。
解决方案
我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
推荐阅读
- c# - C# Excel 互操作:来自 HRESULT 的异常:使用 Range.set_Value 时出现 0x800A03EC
- html - CSS问题:如何对齐元素(、页眉、页脚和正文)与响应式网页设计垂直?
- zend-framework - PHPUNIT Zend 框架如何模拟 Zend_Registry::set 仅针对第一个数据源项进行测试并为第二个取消设置?
- c - 为什么我收到错误消息“s undeclared here not in a function”
- jquery - 如何从laravel中的文件输入中删除文件
- json - 无法从 iSeries (IBM Midrange) 上的 JSON 数据中检索值
- node.js - Socket 在使用 NodeJs 从 Gmail API 获取邮件时挂起
- reactjs - 如何在反应中使用嵌套循环
- python-3.x - 如何求解具有指数项的方程
- arrays - 按值排序的数组排序