rjmccall added a comment.

In http://reviews.llvm.org/D11297#223622, @andreybokhanko wrote:

> John,
>
> Thank you for the quick reply!
>
> Let me make sure I understand what you said, using my test as an example 
> (BTW, sorry if this is a dumb question -- I asked our local Clang experts, 
> but no-one seems to be 100% sure what to do):
>
>   1: struct T {
>   2:   ~T() {}
>   3: };
>   4: 
>   5: extern "C" void _ZN1TD1Ev();
>   6: 
>   7: int main() {
>   8:   _ZN1TD1Ev();
>   9:   T t;
>   10: }
>
>
> When we deal with the call at line N8, there are no Functions created yet, so 
> nothing to bitcast. Thus, we create a Function and the following call:
>
>   call void @_ZN1TD1Ev()


Yes.

> When we deal with implicit destructor call at line N10, there is already a 
> Function with "_ZN1TD1Ev" mangled name exists. Thus, we create a bitcast and 
> the following call:

> 

>   call void bitcast (void ()* @_ZN1TD1Ev to void (%struct.T*)*)(%struct.T* %t)


Yes.

> At the end of IRGen we should replace all references of old _ZN1TD1Ev (one 
> with zero arguments) with new _ZN1TD1Ev (one with a single T* argument) -- 
> *including* adding a new bitcast (as we replace a Function with different 
> type) in all places in IR where we do the replacement.


This is only necessary if you try to emit the definition at some point.  In 
this case, you will, because emitting the reference to the destructor as part 
of the second call will require the destructor to be emitted, because it's 
inline.

Let me try to spell out the sequence more precisely.

1. IRGen starts out with no Function.
2. IRGen sees the declaration of the extern "C" function.  It's just a 
declaration, not a definition, so IRGen doesn't need to do anything.
3. IRGen sees the declaration of the destructor.  It's a definition, but it's a 
deferrable definition, so IRGen doesn't need to do anything except record that 
it's got a deferred definition in DeferredDecls.
4. IRGen emits a reference to the extern "C" function.  This is a reference, 
not a definition, so it's fine for getOrCreateLLVMFunction to return an 
arbitrary Constant; it doesn't have to return a Function.  But we don't have a 
Function yet, so we create one with the expected type for the extern "C" 
function.  We also notice that we've got a deferred definition for this name, 
so we move that to the deferred-decls-to-emit queue.
5. IRGen emits a reference to the destructor.  This is a reference, not a 
definition, so any kind of Constant is fine.  Now, we've got a Function, but 
it's got the wrong type, so we need to bitcast it.  We've already enqueued the 
deferred definition, so that's fine.
6. IRGen emits the deferred definition.  We tell getOrCreateLLVMFunction that 
we're going to define the function, so getOrCreate has to return a Function 
with the right type; it's got an existing llvm::Function, but it's the wrong 
type, so it has to make a new llvm::Function.  It creates a new Function with 
no name, takes the name of the existing Function (with takeName), replaces 
existing references with a bitcast to the new name, and queues up something for 
the end of emission to remove the replaced Function.
7. IRGen reaches the end of emission and sees that it's got a Function to 
replace.  It replaces the Function with a bitcast of the new function again (if 
there are any remaining uses) and then deletes it.

Make sense?


http://reviews.llvm.org/D11297



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to