【问题标题】:LLVM C++ API bitcode loading and executionLLVM C++ API 位码加载和执行
【发布时间】:2020-04-24 09:40:51
【问题描述】:

我正在寻找涵盖 LLVM C++ API 用法的完整示例,特别是从位码(不是拼写错误,他们称之为位码)文件加载函数、运行它并获取结果。我研究了this blog post,我正在尝试将它移植到 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 都可以被同一个函数解析的事实。

【问题讨论】:

  • 您自己立即发布了一个答案,但据我所知,它没有加载位码。你能澄清一下吗? (另外,bitcode 真的是 bitcode,bitstream literally consists of a stream of bits。)
  • 谢谢,你是对的,我同时使用 .bc 和 .ll 文件,最终将 .ll 文件提供给我的应用程序。一切都与 .bc 相同。我将更新clang 命令以输出位码文件。

标签: llvm llvm-c++-api


【解决方案1】:

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

ma​​in.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;
}

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

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

【讨论】:

  • 对我来说,它在ExecutionEngine *executionEngine = ... 行导致Segmentation fault (core dumped)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 2013-03-19
  • 2011-08-29
  • 1970-01-01
  • 2012-09-11
  • 2012-04-07
相关资源
最近更新 更多