[foreign] RFR 8220544: Jextract; library dependent header filtering

Jorn Vernee jbvernee at xs4all.nl
Thu Mar 14 12:45:13 UTC 2019


Updated webrev: 
http://cr.openjdk.java.net/~jvernee/panama/webrevs/8220544/webrev.04/

Changed Treemaker implementation to recurse to the 'root' type when 
creating TypdefTree::def, and using that in DependencyFinder.

Jorn

Jorn Vernee schreef op 2019-03-14 12:49:
> Oh ok, sorry. I'll try that out.
> 
> Jorn
> 
> Maurizio Cimadamore schreef op 2019-03-14 12:43:
>> On 14/03/2019 11:40, Jorn Vernee wrote:
>>> I see what you mean.
>>> 
>>> Well, `struct BAR` has a definition cursor, but `struct BAR*` does 
>>> not have a definition/declaration, it's a type that's automatically 
>>> derived from `struct BAR`. So for `struct BAR*` there is no good 
>>> value for TypedefTree::def.
>> 
>> I know that there's no good value for struct BAR* - I was wondering if
>> the parser should detect the pointer, and recurse down, then store
>> 'struct BAR' into 'def'.
>> 
>> Maurizio
>> 
>>> 
>>> TypedefTree::def seems to be a helper method mostly targeted at 
>>> inline type definitions (looking at TypedefHandler [1]).
>>> 
>>> I think for my use case using TypedefTree.type().canonicalType() is 
>>> good enough, but I guess we could query that once in the parser and 
>>> then store it in a field in TypedefTree?
>>> 
>>> Jorn
>>> 
>>> [1] : 
>>> http://hg.openjdk.java.net/panama/dev/file/43ed53f40957/src/jdk.jextract/share/classes/com/sun/tools/jextract/TypedefHandler.java#l107
>>> 
>>> Maurizio Cimadamore schreef op 2019-03-14 11:57:
>>>> On 14/03/2019 00:23, Jorn Vernee wrote:
>>>>> Sorry, bad example. The actual failure case is:
>>>>> 
>>>>>      struct BAR { int x; }
>>>>> 
>>>>>      typedef struct BAR* FOO;
>>>>> 
>>>>> The TreeMaker code looks at the canonical type of the typedef 
>>>>> `struct BAR*` which is neither a type definition or declaration, so 
>>>>> TypedefTree::def is empty. But, in the case of dependecy analysis, 
>>>>> we still want to inspect that type, get the pointee type and add it 
>>>>> to the root set.
>>>> 
>>>> Right - and I think what I'm claiming is that this is probably some
>>>> kind of a parser bug? That is, if Typedef::def (we should probably
>>>> find another name, 'def' is not good enough IMHO) is set correctly 
>>>> for
>>>> 
>>>> typedef struct BAR FOO;
>>>> 
>>>> it should also be set for
>>>> 
>>>> typedef struct BAR* FOO;
>>>> 
>>>> That is, I claim that from the typedef tree you should always see a
>>>> referenced type declaration w/o using the clang API.
>>>> 
>>>> Maurizio
>>>> 
>>>>> 
>>>>> Jorn
>>>>> 
>>>>> Jorn Vernee schreef op 2019-03-14 01:14:
>>>>>> Maurizio Cimadamore schreef op 2019-03-14 01:04:
>>>>>>> So, if I understand correctly, the issue is that if you have:
>>>>>>> 
>>>>>>> typedef struct { int x; } FOO;
>>>>>>> 
>>>>>>> you want the struct to be added to the root set. Which make 
>>>>>>> sense.
>>>>>>> 
>>>>>>> Now, with respect to getUnderlyingType - I'm a bit at odds; it 
>>>>>>> seems
>>>>>>> to me that the jextract tree should have the right info, under
>>>>>>> TypedefTree::def, at least that is set by the parser for
>>>>>>> declarations/definitions.
>>>>>> 
>>>>>> That exact case is covered by TypedefTree::def, but it doesn't 
>>>>>> cover a
>>>>>> case like this:
>>>>>> 
>>>>>>     struct BAR { int x; }
>>>>>> 
>>>>>>     typedef struct BAR FOO;
>>>>>> 
>>>>>> i.e. TypedefTree::def is only set when the typedef contains an 
>>>>>> inline
>>>>>> definition or a prototype. But, if the type is just referenced,
>>>>>> TypedefTree::def is an empty Optional.
>>>>>> 
>>>>>>> Wouldn't visiting TypedefTree::def (if present) be enough (and 
>>>>>>> more in
>>>>>>> sync with the rest of jextract) ? After all, that's the kind of 
>>>>>>> thing
>>>>>>> you wanna be sure not to miss by the dependency analysis -
>>>>>>> getUnderlyingType seems a tad too noisy?
>>>>>> 
>>>>>> This is what I had before, but it fell short in some cases.
>>>>>> 
>>>>>>> In other words, let's say that there's a typedef in an header of 
>>>>>>> a
>>>>>>> library you want to jextract which is related, via a chain of 
>>>>>>> other 42
>>>>>>> typedefs to something in some obscure system library. Are you 
>>>>>>> sure you
>>>>>>> want the resulting artifact to have all the 42 intermediate 
>>>>>>> typedefs?
>>>>>>> After all, the library you wanna extract has just defined 'its
>>>>>>> version' of the name for that particular construct... so it's 
>>>>>>> very
>>>>>>> likely that users of that library will prefer that name to the 
>>>>>>> other
>>>>>>> 42 ones?
>>>>>> 
>>>>>> 42 intermediate typedefs seems a bit extreme...
>>>>>> 
>>>>>> But, I think you have a point. Putting the typedef and the 
>>>>>> canonical
>>>>>> type into the root set is probably enough.
>>>>>> 
>>>>>> Jorn
>>>>>> 
>>>>>>> Maurizio
>>>>>>> 
>>>>>>> On 13/03/2019 23:31, Jorn Vernee wrote:
>>>>>>>> Update webrev: 
>>>>>>>> http://cr.openjdk.java.net/~jvernee/panama/webrevs/8220544/webrev.02/ 
>>>>>>>> This fixes an issue where typedef underlying types were not 
>>>>>>>> being added to the root set.
>>>>>>>> 
>>>>>>>> It turns out I was using the wrong API to get the underlying 
>>>>>>>> type, and the needed API didn't have a binding yet :)
>>>>>>>> 
>>>>>>>> The changes with respect to the previous webrev;
>>>>>>>>   * added Cursor.getTypedefDeclUnderlyingType() binding
>>>>>>>>   * added TypdefTree.underlyingType() method
>>>>>>>>   * changed DependencyFinder to use this method instead of 
>>>>>>>> typeDefinition()
>>>>>>>>   * added test case for the failure case (also simplified test 
>>>>>>>> class to only run jextract once and reuse the result)
>>>>>>>> 
>>>>>>>> Cheers,
>>>>>>>> Jorn
>>>>>>>> 
>>>>>>>> Maurizio Cimadamore schreef op 2019-03-13 22:43:
>>>>>>>>> On 13/03/2019 21:36, Jorn Vernee wrote:
>>>>>>>>>>> Good questions. When no filter patterns are specified that is 
>>>>>>>>>>> the case
>>>>>>>>>>> everything is outputted, but when filter patterns are 
>>>>>>>>>>> specified
>>>>>>>>>>> headers are only added to the root set if they contain a 
>>>>>>>>>>> symbol that
>>>>>>>>>>> passes the filter.
>>>>>>>>>> 
>>>>>>>>>> FWIW, basically headers with symbols that pass both types of 
>>>>>>>>>> filter are added to the root set. There's 1.) Filtereing based 
>>>>>>>>>> on whether a symbol is found in a library, and 2.) based on 
>>>>>>>>>> the used filter patterns (--include-symbols & 
>>>>>>>>>> --exclude-symbols). I thought it would be better to exclude a 
>>>>>>>>>> header from the root set if all the symbols in it were 
>>>>>>>>>> filtered out by the filter patterns.
>>>>>>>>> 
>>>>>>>>> Yep - I think that sounds sensible
>>>>>>>>> 
>>>>>>>>> Maurizio
>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>> Jorn
>>>>>>>>>> 
>>>>>>>>>> Jorn Vernee schreef op 2019-03-13 22:30:
>>>>>>>>>>> Maurizio Cimadamore schreef op 2019-03-13 22:08:
>>>>>>>>>>>> Hi Jorn,
>>>>>>>>>>>> this looks very good indeed. I'd like to play with it a bit 
>>>>>>>>>>>> before we
>>>>>>>>>>>> go ahead with this, if that's ok.
>>>>>>>>>>> 
>>>>>>>>>>> Please do!
>>>>>>>>>>> 
>>>>>>>>>>>> Also, one question: if the user does not specify "-l" what 
>>>>>>>>>>>> happens? I
>>>>>>>>>>>> guess the root set will then contain all the headers and we 
>>>>>>>>>>>> just get
>>>>>>>>>>>> back the full output (which would be ok) ?
>>>>>>>>>>> 
>>>>>>>>>>> Good questions. When no filter patterns are specified that is 
>>>>>>>>>>> the case
>>>>>>>>>>> everything is outputted, but when filter patterns are 
>>>>>>>>>>> specified
>>>>>>>>>>> headers are only added to the root set if they contain a 
>>>>>>>>>>> symbol that
>>>>>>>>>>> passes the filter.
>>>>>>>>>>> 
>>>>>>>>>>> Maybe we should just fall back to 'include-everything' when 
>>>>>>>>>>> no "-l"
>>>>>>>>>>> options are specified, regardless of filter?
>>>>>>>>>>> 
>>>>>>>>>>> Jorn
>>>>>>>>>>> 
>>>>>>>>>>>> Maurizio
>>>>>>>>>>>> 
>>>>>>>>>>>> On 13/03/2019 18:06, Jorn Vernee wrote:
>>>>>>>>>>>>> Updated webrev: 
>>>>>>>>>>>>> http://cr.openjdk.java.net/~jvernee/panama/webrevs/8220544/webrev.01/ 
>>>>>>>>>>>>> Fixed the bug, also added tests & ran all the examples 
>>>>>>>>>>>>> again to try and find other bugs (nothing found).
>>>>>>>>>>>>> 
>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>> Jorn
>>>>>>>>>>>>> 
>>>>>>>>>>>>> Jorn Vernee schreef op 2019-03-13 17:50:
>>>>>>>>>>>>>> Discovered a bug in this after posting :(
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> DependencyFinder also needs to look for pointee and array 
>>>>>>>>>>>>>> element type
>>>>>>>>>>>>>> cursors (which it currently doesn't). I've tested a 
>>>>>>>>>>>>>> working fix, but
>>>>>>>>>>>>>> will also add some tests for the particular cases. Updated 
>>>>>>>>>>>>>> webrev
>>>>>>>>>>>>>> coming soon™
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Jorn
>>>>>>>>>>>>>> 
>>>>>>>>>>>>>> Jorn Vernee schreef op 2019-03-13 17:21:
>>>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> After some discussion:
>>>>>>>>>>>>>>> https://mail.openjdk.java.net/pipermail/panama-dev/2019-March/004828.html 
>>>>>>>>>>>>>>> I've implemented the discussed approach to header & 
>>>>>>>>>>>>>>> declaration filtering.
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8220544
>>>>>>>>>>>>>>> Webrev: 
>>>>>>>>>>>>>>> http://cr.openjdk.java.net/~jvernee/panama/webrevs/8220544/webrev.00/ 
>>>>>>>>>>>>>>> There are a few new implementation classes:
>>>>>>>>>>>>>>>   * PattertnFilter; a helper class that encapsulates the 
>>>>>>>>>>>>>>> Pattern based
>>>>>>>>>>>>>>> filtering code previously found in SymbolFilter. This 
>>>>>>>>>>>>>>> code had to be
>>>>>>>>>>>>>>> reused.
>>>>>>>>>>>>>>>   * Filters; a Context sub-component holding 
>>>>>>>>>>>>>>> PatternFilters for
>>>>>>>>>>>>>>> different types of declarations.
>>>>>>>>>>>>>>>   * DependencyFinder; finds dependencies of the root set 
>>>>>>>>>>>>>>> of
>>>>>>>>>>>>>>> declarations found in the root headers.
>>>>>>>>>>>>>>>   * ElementFilter; filters out non-library symbol 
>>>>>>>>>>>>>>> elements based on
>>>>>>>>>>>>>>> whether they appear in a root header or are required by 
>>>>>>>>>>>>>>> something
>>>>>>>>>>>>>>> therein.
>>>>>>>>>>>>>>>   * RootSet; a helper class for managing root headers + 
>>>>>>>>>>>>>>> required element Trees.
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> I also encountered some crashes when debug printing 
>>>>>>>>>>>>>>> Trees, which I've
>>>>>>>>>>>>>>> fixed/worked around accordingly.
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> FWIW, I tried this out with the Windows registry API and 
>>>>>>>>>>>>>>> it's working
>>>>>>>>>>>>>>> very nicely! Going from well over 100 headers to under 
>>>>>>>>>>>>>>> 10. Some room
>>>>>>>>>>>>>>> for improvement still exists; some empty headers and 
>>>>>>>>>>>>>>> static forwarders
>>>>>>>>>>>>>>> could still be omitted, but imho that should be handled 
>>>>>>>>>>>>>>> by a separate
>>>>>>>>>>>>>>> patch.
>>>>>>>>>>>>>>> 
>>>>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>>>> Jorn


More information about the panama-dev mailing list