我试图在运行时加载一个在.bc
文件中定义的LLVM模块,但是遇到了一个障碍。
感兴趣的比特代码是从hello.cpp
生成的。
// hello.cpp
// build with:
// clang-3.4 -c -emit-llvm hello.cpp -o hello.bc
#include <iostream>
void hello()
{
std::cout << "Hello, world!" << std::endl;
}
当下面的程序试图在运行时加载它时,它会在llvm::BitstreamCursor::Read()
中崩溃。
// main.cpp
// build with:
// g++ main.cpp `llvm-config-3.4 --cppflags --ldflags --libs` -ldl -lpthread -lcurses
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/raw_ostream.h>
#include <fstream>
#include <iostream>
llvm::Module *load_module(std::ifstream &stream)
{
if(!stream)
{
std::cerr << "error after open stream" << std::endl;
return 0;
}
// load bitcode
std::string ir((std::istreambuf_iterator<char>(stream)), (std::istreambuf_iterator<char>()));
// parse it
using namespace llvm;
LLVMContext context;
SMDiagnostic error;
Module *module = ParseIR(MemoryBuffer::getMemBuffer(StringRef(ir.c_str())), error, context);
if(!module)
{
std::string what;
llvm::raw_string_ostream os(what);
error.print("error after ParseIR()", os);
std::cerr << what;
} // end if
return module;
}
int main()
{
std::ifstream stream("hello.bc", std::ios_base::binary);
llvm::Module *m = load_module(stream);
if(m)
{
m->dump();
}
return 0;
}
我使用注释中提到的命令行构建LLVM v3.4。
知道我做错什么了吗?
发布于 2014-03-18 23:31:59
有两个问题:
LLVMContext
的生存期需要超过Module
的生存期。否则,Module
将引用不再存在的LLVMContext
。StringRef
应该由包含IR的std::string
(而不是以零结尾的字符串)构造。否则,ParseIR
将无法正确找到IR的结尾。以下是修正后的load_module
版本
llvm::Module *load_module(std::ifstream &stream, llvm::LLVMContext &context)
{
if(!stream)
{
std::cerr << "error after open stream" << std::endl;
return 0;
}
// load bitcode
std::string ir((std::istreambuf_iterator<char>(stream)), (std::istreambuf_iterator<char>()));
// parse it
using namespace llvm;
SMDiagnostic error;
Module *module = ParseIR(MemoryBuffer::getMemBuffer(StringRef(ir)), error, context);
if(!module)
{
std::string what;
llvm::raw_string_ostream os(what);
error.print("error after ParseIR()", os);
std::cerr << what;
} // end if
return module;
}
发布于 2014-03-07 05:06:53
一个可能的解决方案是将ParseIR()
调用替换为
ParseIRFile("hello.bc", error, getGlobalContext())
这样做也使代码更加简单,因为您可以跳过尝试手动加载bitcode的部分。
以下内容足以为模块获得转储(您应该在其中添加一些错误处理)
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/Support/SourceMgr.h>
using namespace llvm;
int main()
{
LLVMContext context;
SMDiagnostic error;
Module *m = ParseIRFile("hello.bc", error, context);
if(m)
{
m->dump();
}
return 0;
}
https://stackoverflow.com/questions/22239801
复制相似问题