[LLVMdev] Offset to C++ structure members
Paul J. Lucas
paul at lucasmail.org
Mon Oct 1 21:33:10 PDT 2012
Given the C++ struct:
struct S {
string a;
string b;
};
I also have C "thunk" functions that I call from LLVM code:
// calls S::S()
void* T_S_M_new( void *heap );
// call string::assign(char const*)
void T_string_M_assign_Pv( void *that, void *value );
I want to do the LLVM equivalent of the following C++ (where that 's' is pointer to an instance of 'S'):
s->b.assign( "Hello, world!" ); // assign to S::b
If there were an S member function:
void S::assign_to_b( char const* );
it would be easy to write a "thunk" wrapper to call it. However, assume that there is no such S member function. I therefore need a way to get the offset of 'b' and add it to 's' so that I can call T_string_M_assign_Pv() on it.
Given this helper function:
template<class ClassType,class MbrType> inline
ptrdiff_t mbr_offset_of( MbrType ClassType::*p ) {
ClassType const *const c = static_cast<ClassType*>( nullptr );
return reinterpret_cast<ptrdiff_t>( &(c->*p) );
}
I could take a Pointer to an S, use ptrtoint, add the offset, use inttoptr, and use that pointer to pass as the 'this' argument to T_string_M_assign_Pv(). The LLVM code generated via the IRBuilder is:
%0 = call i8* @T_S_M_new(i8* %heap)
%1 = ptrtoint i8* %0 to i64
%2 = add i64 %1, 8 ; 8 is what's returned by mbr_offset_of()
%3 = inttoptr i64 %2 to i8*
call void @T_string_M_assign_A_Pv(i8* %3, i8* getelementptr inbounds ([15 x i8]* @0, i64 0, i64 0))
The code does in fact work. My questions are:
* Is this an "OK" thing to do?
* Is there a better way?
- Paul
P.S.: I don't explicitly put the getelementptr instruction in there. That's something the IRBuilder does all by itself.
More information about the llvm-dev
mailing list