static inline and jextract

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Sep 6 16:13:43 UTC 2022


Thinking about some more (after some offline internal discussion).

I don't think jextract should be "opinionated" as to how global 
variables are declared in headers. Is there a "correct" way to add 
global variables to a library header? Yes, by using "extern". Does that 
mean that all other declarations should be skipped? That's where I think 
this is taking us too far.

There might be libraries built in non-idiomatic ways, which expect 
developers that use them to do other tweaks. Does it mean that jextract 
should ignore those? That seems harsh.

If Jextract finds a global variable definition in a header file, then it 
should just treat it at face value, w/o asking whether it makes sense or 
not for the header file to be the way it is. After all, that's why we 
also have filters, so that users can exclude symbols based on additional 
domain-level knowledge.

So, I think unless a symbol is explicitly marked as non-exported (e.g. 
because it's static, or inline, as per [1]), then jextract should act on it.

Maurizio

On 06/09/2022 16:08, Manuel Bleichenbacher wrote:
> I mostly agree except for:
>
>     It seems to me that all this boil to two rules:
>
>     * we should only generate global var accessor for "extern" variables
>     * we should skip static symbols (this is covered by [1])
>
> This opens space for a third case: neither "extern" nor "static". I 
> think it boils down to a single rule:
>
>   * For variables: generate code if declared as "extern", skip otherwise
>
>
> On Tue, Sep 6, 2022 at 4:37 PM Maurizio Cimadamore 
> <maurizio.cimadamore at oracle.com> wrote:
>
>     Some replies inline:
>
>
>     On 06/09/2022 15:08, Manuel Bleichenbacher wrote:
>>     I think there are only a few cases:
>>
>>     Case 1: extern int i;
>>     It is a declaration and should generate the lookup for a symbol
>>     "i" (plus a method to get the value). It is already implemented
>>     like this.
>     I agree this is the most idiomatic way to do things.
>>
>>     Case 2: int i = 4;
>>     It can be skipped as it never appears in a header file that can
>>     be consumed by multiple compilation units (as it would generate
>>     an error). It's simply not relevant for jextract, which generates
>>     code to access an existing library.
>>
>>     Case 3: int i;
>>     It is the same as case 2 (implicitly initializes to 0).
>
>     I also agree that these two seem suspicious. While in a standalone
>     application, an header containg symbols like these might make
>     sense, in a library, this most likely does not make any sense, as
>     it will create storage in all clients importing the headerfile.
>
>
>>
>>     Case 4: int __declspec(selectany) i = 4;
>>     This is a special case *and most likely Microsoft specific). In
>>     theory, the behavior could be replicated, i.e. a variable or
>>     constant is allocated in native memory and properly initialized.
>>     Since it's a rare case, I'd rather skip it.
>
>     Yes, this seems to be special and unique to Windows. But, I'd
>     rather gate on presence of "extern", than to obscure __declspec.
>
>
>
>>
>>     Case 5: static int i = 4;
>>     It is a mixture between case 2 and 4. It's unlikely to appear in
>>     header files although it does not generate an error. The behavior
>>     could be replicated but I would spend time on more important
>>     things and skip it for now.
>>
>>     Case 6: static int i;
>>     It is the same as case 5 (implicitly initializes to 0).
>
>     These seem easier, since declaration says "static".
>
>
>     It seems to me that all this boil to two rules:
>
>     * we should only generate global var accessor for "extern" variables
>     * we should skip static symbols (this is covered by [1])
>
>     Maurizio
>
>     [1] - https://github.com/openjdk/jextract/pull/70
>     <https://urldefense.com/v3/__https://github.com/openjdk/jextract/pull/70__;!!ACWV5N9M2RV99hQ!Lbol2roLw9oo_l0GVBCHT9dbxHa0KQGBPdKqbBD18RKaDeuM_ajfqaRi1j0hXELnSrtW6HNUS1X8hErjVv5juTzsQlwnawetxw$>
>
>
>>
>>     On Tue, Sep 6, 2022 at 3:29 PM Maurizio Cimadamore
>>     <maurizio.cimadamore at oracle.com> wrote:
>>
>>         Hi,
>>         I think there's more to it.
>>
>>         On Linux, if I do the following:
>>
>>         ```
>>         $ cat foo.h
>>         int i = 4;
>>         ```
>>
>>         and:
>>
>>         ```
>>         $ cat foo.c
>>         #include "foo.h"
>>         ```
>>
>>         And then I compile into a shared lib, the obtained foo.so
>>         does have a symbol for "i" (rightfully so):
>>
>>         ```
>>         $ objdump -T foo.so
>>
>>         foo.so:     file format elf64-x86-64
>>
>>         DYNAMIC SYMBOL TABLE:
>>         0000000000000000  w   D  *UND* 0000000000000000 __cxa_finalize
>>         0000000000000000  w   D  *UND* 0000000000000000
>>         _ITM_registerTMCloneTable
>>         0000000000000000  w   D  *UND* 0000000000000000
>>         _ITM_deregisterTMCloneTable
>>         0000000000000000  w   D  *UND* 0000000000000000 __gmon_start__
>>         0000000000004020 g    DO .data 0000000000000004 i
>>
>>         ```
>>
>>         E.g. the above header contains a *definition*, so the
>>         compiler will create storage for it (and add it to the shared
>>         library), and "i" can be looked up in the shared lib.
>>         Conversely, a global marked as "extern" might or might not be
>>         present in the shared library (depending on whether it's
>>         defined in one of the associated C/CPP files).
>>
>>         Maurizio
>>
>>
>>         On 06/09/2022 13:57, Manuel Bleichenbacher wrote:
>>>         There are two indications that it's definition and not a
>>>         declaration:
>>>
>>>         - absence of "extern" keyword
>>>         - presence of initialization ( = { 0x... )
>>>
>>>         If it was compiled as C/C++ code, it would allocate memory
>>>         in the current compilation unit while a declaration would
>>>         just refer to something outside the compilation unit.
>>>
>>>         Definitions are rare in header files as they usually lead to
>>>         duplicate symbol errors at link time. But through the magic
>>>         of __declspec(selectany), this is avoided.
>>>
>>>         On Tue, Sep 6, 2022 at 12:11 PM Maurizio Cimadamore
>>>         <maurizio.cimadamore at oracle.com> wrote:
>>>
>>>
>>>             On 05/09/2022 16:32, Manuel Bleichenbacher wrote:
>>>             > extern "C" const GUID __declspec(selectany)
>>>             GUID_DEVINTERFACE_USB_DEVICE
>>>             >     = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F,
>>>              0x00,  0xC0,
>>>             >  0x4F,  0xB9,  0x51,  0xED } };
>>>             >
>>>             I guess the problem here is the lack of "dllexport", right?
>>>
>>>             But, while dllexport is common, some libraries can still
>>>             export symbols
>>>             using a .def file [1].
>>>
>>>             So, I'm not sure this belongs in the same category as
>>>             "static inline",
>>>             as it is not possible, just by looking at the header, to
>>>             understand
>>>             whether the symbol will be present or not?
>>>
>>>             [1] -
>>>             https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files?view=msvc-170
>>>             <https://urldefense.com/v3/__https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-def-files?view=msvc-170__;!!ACWV5N9M2RV99hQ!IZ9OZ1GPWyZCLxdiYrnGJewYmhC_BCpH8sxH4Lo2jBtSsuMJPH_j3-vIXRO1emIKo2SMrT3Sj1AqI3daPLx2VOq6oGrpPgb-Xw$>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jextract-dev/attachments/20220906/7561f7a5/attachment-0001.htm>


More information about the jextract-dev mailing list