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 );
/ / ...
};
I know that LLVM knows nothing about C. One way to call C functions is to wrap them in a 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"
The first question is how to get from LLVM Assign items. I know how to create StructTypes and add words to them Paragraph, but I don’t want to be parallel to the C-type layout-it is tedious and error-prone.
The idea I get is just to add a char [sizeof(T)] as the only field of the C-type StructType:
StructType *const llvm_item_type = StructType::create( llvm_ctx, "item" );
vectorllvm_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 );
I think, because it is a StructType, the alignment is correct and the size of sizeof(item) is correct. Would that be useful? Is there a better way?
The second problem is that, unlike the C class hierarchy, there is no inheritance relationship between StructType. If I create a Function that accepts llvm_iterator_type but try to use llvm_singleton_iterator_type to build a Function object, the LLVM verifyModule() function will Complain to me:
The call parameter type does not match the function signature!
Then I thought I was just using void * everywhere:
Type *const llvm_void_type = Type::getVoidTy( llvm_ctx );
PointerType *const llvm_void_ptr_type = PointerType::getUnqual( llvm_void_type );
However, verifyModule() still complains to me because obviously, there is no automatic conversion to void * in LLVM. How can I solve this problem?
As for the “call parameter type does not match the function signature!” error, the solution is to make all thunks use void * and use it in it static_casts. When passing parameters to thunk, please use the CreateBitCast()IRBuilder function (because in LLVM, casts-tovoid is not automatic).
My project has one C library, I want to allow users to use JIT through a certain programming language to call the functions in the library. For simplicity, suppose the library has the following classes:
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 );
// ...
};
I know that LLVM knows nothing about C. One way to call C functions is to wrap them in a C thunk:
extern "C" {
void thunk_item_M_new( item *addr) {
new( addr) item;
}
void thunk_singleton_iterator_M_new( singleton_iterator *addr, i tem *i) {
new( addr) singleton_iterator( *i );
}
bool thunk_iterator_M_next( item_iterator *that, item *result) {
return that ->next( result );
}
} // extern "C"
The first question is how to allocate items from LLVM. I know how to create StructTypes And add fields to them, but I don’t want to be parallel to the C class layout-this is tedious and error-prone.
The idea I get is just to add a char [sizeof(T)] as the StructType of the C class type The only field of :
StructType *const llvm_item_type = StructType::create( llvm_ctx, "item" );
vectorllvm_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 *constptr_type = llvm_item_type ::getUnqual( llvm_item_type );
I think, because it is a StructType, the alignment is correct, and the size of sizeof(item) is correct. Would that be useful? Is there a better way?
The second problem is that, unlike the C class hierarchy, there is no inheritance relationship between StructType. If I create a Function that accepts llvm_iterator_type but try to use llvm_singleton_iterator_type to build a Function object, the LLVM verifyModule() function will Complain to me:
The call parameter type does not match the function signature!
Then I thought I was just using void * everywhere:
Type *const llvm_void_type = Type::getVoidTy( llvm_ctx );
PointerType *const llvm_void_ptr_type = PointerType::getUnqual( llvm_void_type );
However, verifyModule() still complains to me because obviously, there is no automatic conversion to void * in LLVM. How can I solve this problem?
It turns out that using char [sizeof(T)] is a reasonable way to make StructTypes the correct size-at least one other person from the LLVM mailing list does this .
As for the “call parameter type does not match the function signature!” error, the solution is to make all thunks use void * and use static_casts in them. When passing parameters to the thunk, please use CreateBitCast ()IRBuilder function (because casts-tovoid is not automatic in LLVM).