使用LLVM JIT代码对程序进行编码以调用C ++代码

时间:2012-03-15 00:23:26

标签: c++ llvm jit

我的项目有一个C ++库,我希望允许用户通过某种编程语言使用JIT来调用所述库中的函数。为简单起见,假设库具有以下类:

class item {
public:
  item();
  item( int );
  ~item();
  // ...
};

class item_iterator {
public:
  virtual ~item_iterator();
  virtual bool next( item *result ) = 0;
};

class singleton_iterator : public item_iterator {
public:
  singleton_iterator( item const &i );
  // ...
};

我知道LLVM对C ++一无所知,调用C ++函数的一种方法是将它们包装在C thunk中:

extern "C" {

  void thunk_item_M_new( item *addr ) {
    new( addr ) item;
  }

  void thunk_singleton_iterator_M_new( singleton_iterator *addr, item *i ) {
    new( addr ) singleton_iterator( *i );
  }

  bool thunk_iterator_M_next( item_iterator *that, item *result ) {
    return that->next( result );
  }

} // extern "C"

第一个问题是如何从LLVM分配item。我知道如何创建StructType并向其添加字段,但我不想与C ++类布局并行 - 这很乏味且容易出错。

我得到的想法只是将char[sizeof(T)]作为唯一字段添加到StructType的C ++类类型中:

StructType *const llvm_item_type = StructType::create( llvm_ctx, "item" );
vector<Type*> llvm_struct_types;
llvm_struct_types.push_back( ArrayType::get( IntegerType::get( llvm_ctx, 8 ), sizeof( item ) ) );
llvm_item_type->setBody( llvm_struct_types, false );
PointerType *const llvm_item_ptr_type = PointerType::getUnqual( llvm_item_type );

我认为,因为它是StructType,所以对齐方式是正确的,而sizeof(item)会得到正确的大小。那会有用吗?还有更好的方法吗?

第二个问题是,与C ++类层次结构不同,StructType之间没有继承关系。如果我创建一个Function,它使用llvm_iterator_type但尝试使用Function构建llvm_singleton_iterator_type对象,则LLVM verifyModule()函数会向我抱怨:

调用参数类型与函数签名不匹配!

那么我以为我只是在任何地方使用void*

Type *const llvm_void_type = Type::getVoidTy( llvm_ctx );
PointerType *const llvm_void_ptr_type = PointerType::getUnqual( llvm_void_type );

但是verifyModule()仍然抱怨我,因为显然,LLVM中没有自动转换为void*类型。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:5)

事实证明,使用char[sizeof(T)]是使StructType成为正确大小的合理方法 - 来自LLVM邮件列表的至少另一个人这样做。

“调用参数类型与函数签名不匹配!”错误,解决方案只是让所有thunk使用void*并在里面使用static_cast。将参数传递给thunk时,请使用CreateBitCast() IRBuilder函数(因为强制转换为void在LLVM中不是自动的。)