首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从ifstream加载LLVM位码文件?

如何从ifstream加载LLVM位码文件?
EN

Stack Overflow用户
提问于 2014-03-07 01:37:49
回答 2查看 3.4K关注 0票数 5

我试图在运行时加载一个在.bc文件中定义的LLVM模块,但是遇到了一个障碍。

感兴趣的比特代码是从hello.cpp生成的。

代码语言:javascript
运行
复制
// 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()中崩溃。

代码语言:javascript
运行
复制
// 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。

知道我做错什么了吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-18 23:31:59

有两个问题:

  1. LLVMContext的生存期需要超过Module的生存期。否则,Module将引用不再存在的LLVMContext
  2. 引用IR的StringRef应该由包含IR的std::string (而不是以零结尾的字符串)构造。否则,ParseIR将无法正确找到IR的结尾。

以下是修正后的load_module版本

代码语言:javascript
运行
复制
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;
}
票数 6
EN

Stack Overflow用户

发布于 2014-03-07 05:06:53

一个可能的解决方案是将ParseIR()调用替换为

ParseIRFile("hello.bc", error, getGlobalContext())

这样做也使代码更加简单,因为您可以跳过尝试手动加载bitcode的部分。

以下内容足以为模块获得转储(您应该在其中添加一些错误处理)

代码语言:javascript
运行
复制
#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;
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22239801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档