operator new

Hi.

Is there a way to understand what class(struct) was created by operator new by analysing generated bytecode?

I thought that after %call = tail call noalias i8* @_Znwj(i32 <size>) is goes bitcast of %call to need struct, but for next example it is wrong.

For exampe I have a function:

Query* WildcardQuery::clone() const{
  return _CLNEW WildcardQuery(*this);
}

And bytecode for this:

define %"class.lucene::search::Query.1814"* @_ZNK6lucene6search13WildcardQuery5cloneEv(%"class.lucene::search::WildcardQuery.2404"* nocapture %this) align 2 {
entry:
  %call = tail call noalias i8* @_Znwj(i32 12)
  %0 = bitcast i8* %call to %"class.lucene::search::MultiTermQuery.1815"*
  %1 = getelementptr inbounds %"class.lucene::search::WildcardQuery.2404"* %this, i32 0, i32 0
  invoke void @_ZN6lucene6search14MultiTermQueryC2ERKS1_(%"class.lucene::search::MultiTermQuery.1815"* %0, %"class.lucene::search::MultiTermQuery.1815"* %1)
          to label %invoke.cont unwind label %lpad

invoke.cont: ; preds = %entry
  %2 = bitcast i8* %call to i32 (...)***
  store i32 (...)** bitcast (i8** getelementptr inbounds ([13 x i8*]* @_ZTVN6lucene6search13WildcardQueryE, i32 0, i32 2) to i32 (...)**), i32 (...)*** %2, align 4
  %3 = bitcast i8* %call to %"class.lucene::search::Query.1814"*
  ret %"class.lucene::search::Query.1814"* %3

lpad: ; preds = %entry
  %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
          cleanup
  tail call void @_ZdlPv(i8* %call) nounwind
  resume { i8*, i32 } %4
}

Yours sincerely,
Kadysev Mikhail

Hi.

Is there a way to understand what class(struct) was created by operator new by analysing generated bytecode?

I thought that after %call = tail call noalias i8* @_Znwj(i32 <size>) is goes bitcast of %call to need struct, but for next example it is wrong.

For exampe I have a function:

Query* WildcardQuery::clone() const{
  return _CLNEW WildcardQuery(*this);
}

And bytecode for this:

define %"class.lucene::search::Query.1814"* @_ZNK6lucene6search13WildcardQuery5cloneEv(%"class.lucene::search::WildcardQuery.2404"* nocapture %this) align 2 {
entry:
%call = tail call noalias i8* @_Znwj(i32 12)
%0 = bitcast i8* %call to %"class.lucene::search::MultiTermQuery.1815"*
%1 = getelementptr inbounds %"class.lucene::search::WildcardQuery.2404"* %this, i32 0, i32 0
invoke void @_ZN6lucene6search14MultiTermQueryC2ERKS1_(%"class.lucene::search::MultiTermQuery.1815"* %0, %"class.lucene::search::MultiTermQuery.1815"* %1)
         to label %invoke.cont unwind label %lpad

That's the inlined base constructor.

invoke.cont: ; preds = %entry
%2 = bitcast i8* %call to i32 (...)***
store i32 (...)** bitcast (i8** getelementptr inbounds ([13 x i8*]* @_ZTVN6lucene6search13WildcardQueryE, i32 0, i32 2) to i32 (...)**), i32 (...)*** %2, align 4

That's the inlined vtable initialization.

%3 = bitcast i8* %call to %"class.lucene::search::Query.1814"*
ret %"class.lucene::search::Query.1814"* %3

And that's the cast to the return type.

The question is, why is the constructor of WildcardQuery inlined here? Did you run any inlining pass? (It could be that Clang inlines trivial constructors itself.)

Sebastian

Nothing you do on LLVM IR here is ever going to be more than a best-effort approximation; really you should be looking at the AST, not LLVM IR.

John.