Checking if function have been emitted

Hi,
I would like to check if there is inline virtual function that was not emitted.

I tried to do something like this based on CodeGenModule::GetOrCreateLLVMFunction:

StringRef Name = CGM.getMangledName(VFunction);
auto *Entry = CGM.GetGlobalValue(Name);

// If function doesn’t exist or doesn’t have a definition.
if (!Entry || Entry->isDeclaration())
return true;

But Entry->isDeclaration() returns True for functions that I would expect to be emited.
What is the proper way of checking that?

Thanks for help!
Piotr

PS:
here is the patch that doesn’t work, to get wider scope.
https://reviews.llvm.org/D28178

friendly ping

isDeclaration() only returns true for a function that does not have a body / hasn’t been materialized yet. Do you observe that it is not the case in practice? Or are you trying to look if a function will be emitted by clang but hasn’t already?

Maybe there is something I am missing, but I though vtables are being generated at the end of translation unit.
If there is nothing clang emits after vtable (maybe except inline virtual functions if they are reffered by vtable), then if there is a direct call to inline function, the function has to be emitted before
vtables.

I would like to emit available_externally vtable only if all inline virtual functions has been emitted.
It seems that I find function like virtual default destructor, that should be emitted before vtables (because there is implicit destructor call), but isDeclaration() return true for it.

Test case like:

struct A {
virtual void foo();
virtual ~A() {};
};

void test() {
A a; // This will force emit of A’s destructor.
}

Maybe there is something I am missing, but I though vtables are being generated at the end of translation unit.
If there is nothing clang emits after vtable (maybe except inline virtual functions if they are reffered by vtable), then if there is a direct call to inline function, the function has to be emitted before
vtables.

This is a fixed-point(-ish) problem: emitting a v-table can require more virtual functions which can require more v-tables. So we just add stuff to queues and drain all the queues in a loop.

I would like to emit available_externally vtable only if all inline virtual functions has been emitted.
It seems that I find function like virtual default destructor, that should be emitted before vtables (because there is implicit destructor call), but isDeclaration() return true for it.

You cannot rely on exact order like this in the normal emission code. IRGen does not and will not guarantee it.

You could make a separate pass after the lazy-emission loop.

John.

Maybe there is something I am missing, but I though vtables are being
generated at the end of translation unit.
If there is nothing clang emits after vtable (maybe except inline virtual
functions if they are reffered by vtable), then if there is a direct call
to inline function, the function has to be emitted before
vtables.

This is a fixed-point(-ish) problem: emitting a v-table can require more
virtual functions which can require more v-tables. So we just add stuff to
queues and drain all the queues in a loop.

I would like to emit available_externally vtable only if all inline
virtual functions has been emitted.
It seems that I find function like virtual default destructor, that should
be emitted before vtables (because there is implicit destructor call), but
isDeclaration() return true for it.

You cannot rely on exact order like this in the normal emission code.
IRGen does not and will not guarantee it.

You could make a separate pass after the lazy-emission loop.

John.

Thanks John, that would make sense. By 'separate pass' you mean do it in

CodeGenModule::Release?

Piotr

Immediately after EmitDeferred(), yes. (But as a separate function, please.)

John.

Maybe there is something I am missing, but I though vtables are being
generated at the end of translation unit.
If there is nothing clang emits after vtable (maybe except inline virtual
functions if they are reffered by vtable), then if there is a direct call
to inline function, the function has to be emitted before
vtables.

This is a fixed-point(-ish) problem: emitting a v-table can require more
virtual functions which can require more v-tables. So we just add stuff to
queues and drain all the queues in a loop.

I would like to emit available_externally vtable only if all inline
virtual functions has been emitted.
It seems that I find function like virtual default destructor, that
should be emitted before vtables (because there is implicit destructor
call), but isDeclaration() return true for it.

You cannot rely on exact order like this in the normal emission code.
IRGen does not and will not guarantee it.

You could make a separate pass after the lazy-emission loop.

John.

Thanks John, that would make sense. By 'separate pass' you mean do it in

CodeGenModule::Release?

Immediately after EmitDeferred(), yes. (But as a separate function,
please.)

John.

Of course. Thanks Mehdi and John!