[cfe-dev] Function pointer type becomes empty struct

Christian Dehnert via cfe-dev cfe-dev at lists.llvm.org
Sat Nov 19 02:10:14 PST 2016


Hi David,

> On 17 Nov 2016, at 23:55, David Wiberg <dwiberg at gmail.com> wrote:
> 
> Hi Chris,
> 
> 2016-11-13 12:49 GMT+01:00 Christian Dehnert via cfe-dev
> <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>>:
>> 
>> […]
> 
> TL;DR - Clang tries to determine LLVM IR types related to the first
> function but bails out due to the recursive nature of the type
> hierarchy.
> 
> I thought this was an interesting question so I spent some time trying
> to understand what happens. I can't however say if the behavior is
> correct. Note that I haven't looked at this code previously so please
> correct me if I've misunderstood something.
> 
> - Clang handles top level declarations first. In your example the
> first one is the function "h". To be able to emit LLVM IR, information
> about the function is collected. One thing done is to iterate over the
> function arguments (to determine IR types?). The first interesting
> argument is the pointer to struct A.
> - To compute the layout of the struct, there's an iteration over the
> struct fields which eventually triggers an attempt to get the LLVM
> type for each field.
>  - The first field is a function pointer and an attempt is made to
> gather information regarding the function. But since this function is
> the same as the one we are currently processing, this attempt is
> aborted (to avoid recursion?) and an empty struct is created as type
> instead. This is the unexpected type you see in your output.
>  - The second field is also a function pointer but the main
> difference is that this function type isn't currently being processed
> which means that it can be handled. (The handling actually leads into
> the same call stack as for the previous function. But in this case,
> once the pointer to struct A argument is found, it is determined that
> the struct is currently being processed and further handling is
> deferred.) Since it was possible to handle the function the expected
> type is returned.

Thanks for the in-depth analysis of what is happening here! To me it is a bit strange that what I get depends on the ordering of functions in the input file even though this ordering is irrelevant at the C level, but I can roughly follow what’s happening internally here.

>> […]
> 
> If you insert a function first which doesn't use struct A there's no
> need to determine the types for the struct and the behavior stays the
> same.
> 
>> […]
> 
> If you insert a function which uses struct A but doesn't cause the
> recursive behavior when looking up the types of struct A you get the
> wanted behavior.
> 
> One possible way of fixing this (if it is considered an issue) might
> be to defer the handling of structs if they contain fields with
> function pointers. I'm however not sure that this is correct or if it
> has unwanted side-effects.

We’re just using LLVM-IR emitted by clang in a stand-alone academic tool and needed to understand what our parser did not like about the IR in this case, so I guess the thing we need to fix is probably our parser (and our current view on LLVM-IR).

Putting aside the (at least to me) surprising behavior of the IR generation, I was told in the LLVM IRC channel that the IR is currently undergoing transition to remove types of pointers where they are not needed and rather have opaque pointers:

https://www.youtube.com/watch?v=OWgWDx_gB1I <https://www.youtube.com/watch?v=OWgWDx_gB1I>

Therefore, if I understand correctly, we cannot expect the types in the struct any more, but the type information is rather given on instructions.

Thanks again for your effort here!

Best wishes,
Chris

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20161119/cda288a4/attachment.html>


More information about the cfe-dev mailing list