[erlang-patches] customized ERL_NIF_TERM type support

Daniel Goertzen daniel.goertzen@REDACTED
Thu Feb 13 18:18:10 CET 2014


Thank you for the details.

I see that there are gcc code generation options to choose register or
stack returns for short structs (-fpcc-struct-return and
-freg-struct-return).  If not specified the platform default is selected,
whatever that may be.  "register" returns must be selected for the tests we
are compiling this week, but on your test years ago "stack" must have been
selected.

Anyway, for my use case I am comfortable going ahead with struct{int} usage.

Thanks again for leading me to the answer,
Dan.



On Thu, Feb 13, 2014 at 10:19 AM, Sverker Eriksson <
sverker.eriksson@REDACTED> wrote:

> As I remember, it was the convention of *returning* int vs struct{int}
> that differed (at least).
> int was returned in a register while struct{int} was stored on stack and
> returning
> pointer to it in register.
>
> Maybe there is a difference between C and C++ conventions also.
>
> The top commit on this branch was my attempt with a struct:
>
> git fetch https://github.com/sverker/otp.git ERL_NIF_TERM_as_struct
>
>
> Just did a little test myself now:
>
> struct X {
>     int b;
> };
>
> struct X bar(struct X);
> int foo(int x);
>
>
> int main()
> {
>     struct X a = {0x77};
>     struct X x = bar(a);
>     int y = foo(0x88);
>
>     return x.b + y;
> }
>
> And gcc 4.6.3 uses the same calling conventions for foo and bar (arg in
> edi and return value in eax)
> on my x86_64 Linux machine.
>
> I don't remember if it was some other architecture that I saw the
> difference on.
>
>
> /Sverker
>
>
>
>
>
> On 02/13/2014 04:37 PM, Daniel Goertzen wrote:
>
>> Hi Sverker.
>>
>> I want to look at the bad performance issue you observed with respect to
>> passing "struct{int}" as a parameter vs just passing "int".  I wrote a
>> tiny
>> test program to observe the assembly generated by gcc and the code for the
>> two cases looked identical.  Also, some research into calling conventions
>> hasn't offered me any explanations yet.
>>
>> Do you have any details you can share that will help me understand when
>> and
>> why performance degrades?
>>
>> I want to understand because I am looking at a struct{int} approach as
>> part
>> of a C++ nif solution, and I am very sensitive about adding bloat.
>>
>> Thanks,
>> Dan.
>>
>>
>>
>>
>> On Fri, Feb 7, 2014 at 12:46 PM, Sverker Eriksson <
>> sverker.eriksson@REDACTED> wrote:
>>
>>    Thanks for the patch.
>>>
>>> I got one objection/question though. My C++ knowledge is a bit rusty but
>>> as I understand it
>>> the "enum class" construct demands that Type is an integer type.
>>>
>>> This is currently true for ERL_NIF_TERM but it might not be in the
>>> future.
>>> I earlier tried to define ERL_NIF_TERM as
>>>
>>> typedef struct { int x; } ERL_NIF_TERM;
>>>
>>> to get stronger type checking even for C. I reverted that due to bad
>>> performance
>>> as gcc has different calling conventions for int and struct {int}.
>>> However, future compilers
>>> might be better at passing struct{int} by value in which case we might
>>> want to change
>>> the definition of ERL_NIF_TERM.
>>>
>>> What then? Do we ignore CUSTOM_NIF_TERM_TYPE in such a scenario?
>>>
>>>
>>> /Sverker, Erlang/OTP
>>>
>>>
>>>
>>> On 02/07/2014 06:34 PM, Daniel Goertzen wrote:
>>>
>>> When writing NIFs in C++, it is impossible to employ C++ function
>>> overloading because the underlying type of ERL_NIF_TERM is "unsigned
>>> int".
>>> For example:
>>>
>>> // won't compile :(
>>> #include <erl_nif.h>
>>> void my_func(ERL_NIF_TERM a)  {...}
>>> void my_func(unsigned int a)  {...}
>>>
>>>
>>> This patch allows NIF authors to mutate the type of ERL_NIF_TERM by
>>> defining the macro CUSTOM_NIF_TERM_TYPE().  In the example below, the
>>> underlying unsigned integer type gets wrapped as a C++11 typed
>>> enumeration.  The type of ERL_NIF_TERM is now unique and can be used in
>>> overloaded functions.
>>>
>>> // compiles!  :)
>>> #define CUSTOM_NIF_TERM_TYPE(Type) enum class ERL_NIF_TERM : Type {};
>>> #include <erl_nif.h>
>>> void my_func(ERL_NIF_TERM a)  {...}
>>> void my_func(unsigned int a)  {...}
>>>
>>>
>>> The patch has no impact on erl_nif.h if CUSTOM_NIF_TERM_TYPE is not
>>> defined
>>> (other than flipping the definition order of ERL_NIF_TERM and
>>> ERL_NIF_UINT).
>>>
>>> A similar approach has been used on my C++11 NIF wrapper (
>>> https://github.com/goertzenator/nifpp).  The wrapper requires manual
>>>
>>> installation of a similar patch, and I would love to remove that
>>> requirement.
>>>
>>> Regards,
>>> Dan.
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> erlang-patches mailing listerlang-patches@REDACTED://
>>> erlang.org/mailman/listinfo/erlang-patches
>>>
>>>
>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-patches/attachments/20140213/4e3320b7/attachment.htm>


More information about the erlang-patches mailing list