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