Re: How to overload member function pointer and a regualr member function

2017-04-26 Thread ParticlePeter via Digitalmars-d-learn

On Wednesday, 26 April 2017 at 08:24:08 UTC, Basile B. wrote:

On Tuesday, 25 April 2017 at 18:58:58 UTC, Ali Çehreli wrote:

On 04/25/2017 11:54 AM, Ali Çehreli wrote:
My analysis is wrong because that writefln() is for the 
bar(float) overload but I still think what you want is 
achieved.


Ali


No it's ok, it works. The additional indirection is well 
avoided:


Let's take this module:

==
#!dmd -release -inline -O
module runnable;

struct Foo
{
private void function(int,float) _bar;
void bar(float){}
pragma(inline, false) void bar(int i, float f){_bar(i,f);}
}

struct FooInline
{
private void function(int,float) _bar;
void bar(float){}
pragma(inline, true) void bar(int i, float f){_bar(i,f);}
}

void testInlined(ref FooInline foo)
{
foo.bar(0,0);
}

void test(ref Foo foo)
{
foo.bar(0,0);
}

void main()
{
import disassembler, std.stdio;
disassembler.symbolTable.addModule!runnable;
prettyDisasm().writeln;
prettyDisasm(, 2).writeln; // dig up to 2 levels, 
required for the indir.

}
==

and looks at the output:


;--- SUB 00459970h ---
; NAMED: testInlined
00459970h  push rbp
00459971h  mov rbp, rsp
00459974h  sub rsp, 20h
00459978h  mov qword ptr [rbp-08h], rdi
0045997Ch  xor edi, edi
0045997Eh  mov dword ptr [rbp-20h], edi
00459981h  movss xmm0, dword ptr [rbp-20h]
00459986h  mov rax, qword ptr [rbp-08h]
0045998Ah  call qword ptr [rax]
0045998Dh  mov rsp, rbp
00459990h  pop rbp
00459991h  ret
;-


;--- SUB 00459934h ---
; XREFS: [004599A6h]
00459934h  push rbp
00459935h  mov rbp, rsp
00459938h  sub rsp, 10h
0045993Ch  mov qword ptr [rbp-08h], rdi
00459940h  mov rdi, rsi
00459943h  mov rax, qword ptr [rbp-08h]
00459947h  call qword ptr [rax]
0045994Ah  mov rsp, rbp
0045994Dh  pop rbp
0045994Eh  ret
;-

;--- SUB 00459994h ---
; NAMED: test
00459994h  push rbp
00459995h  mov rbp, rsp
00459998h  sub rsp, 10h
0045999Ch  xor esi, esi
0045999Eh  mov dword ptr [rbp-10h], esi
004599A1h  movss xmm0, dword ptr [rbp-10h]
004599A6h  call 00459934h
004599ABh  mov rsp, rbp
004599AEh  pop rbp
004599AFh  ret
;-

 - testInlined() contains only the delegate call. (call qword 
ptr [rax])
 - test() contains a call (call 00459934h) which 
contains the

   delegate call (call qword ptr [rax])

Actually i've even had to add (pragma inline false) to show the 
difference since DMD inlined automatically bar() in test().


Guys, you're great! Thanks a lot!


Re: How to overload member function pointer and a regualr member function

2017-04-26 Thread Basile B. via Digitalmars-d-learn

On Tuesday, 25 April 2017 at 18:58:58 UTC, Ali Çehreli wrote:

On 04/25/2017 11:54 AM, Ali Çehreli wrote:
My analysis is wrong because that writefln() is for the 
bar(float) overload but I still think what you want is achieved.


Ali


No it's ok, it works. The additional indirection is well avoided:

Let's take this module:

==
#!dmd -release -inline -O
module runnable;

struct Foo
{
private void function(int,float) _bar;
void bar(float){}
pragma(inline, false) void bar(int i, float f){_bar(i,f);}
}

struct FooInline
{
private void function(int,float) _bar;
void bar(float){}
pragma(inline, true) void bar(int i, float f){_bar(i,f);}
}

void testInlined(ref FooInline foo)
{
foo.bar(0,0);
}

void test(ref Foo foo)
{
foo.bar(0,0);
}

void main()
{
import disassembler, std.stdio;
disassembler.symbolTable.addModule!runnable;
prettyDisasm().writeln;
prettyDisasm(, 2).writeln; // dig up to 2 levels, 
required for the indir.

}
==

and looks at the output:


;--- SUB 00459970h ---
; NAMED: testInlined
00459970h  push rbp
00459971h  mov rbp, rsp
00459974h  sub rsp, 20h
00459978h  mov qword ptr [rbp-08h], rdi
0045997Ch  xor edi, edi
0045997Eh  mov dword ptr [rbp-20h], edi
00459981h  movss xmm0, dword ptr [rbp-20h]
00459986h  mov rax, qword ptr [rbp-08h]
0045998Ah  call qword ptr [rax]
0045998Dh  mov rsp, rbp
00459990h  pop rbp
00459991h  ret
;-


;--- SUB 00459934h ---
; XREFS: [004599A6h]
00459934h  push rbp
00459935h  mov rbp, rsp
00459938h  sub rsp, 10h
0045993Ch  mov qword ptr [rbp-08h], rdi
00459940h  mov rdi, rsi
00459943h  mov rax, qword ptr [rbp-08h]
00459947h  call qword ptr [rax]
0045994Ah  mov rsp, rbp
0045994Dh  pop rbp
0045994Eh  ret
;-

;--- SUB 00459994h ---
; NAMED: test
00459994h  push rbp
00459995h  mov rbp, rsp
00459998h  sub rsp, 10h
0045999Ch  xor esi, esi
0045999Eh  mov dword ptr [rbp-10h], esi
004599A1h  movss xmm0, dword ptr [rbp-10h]
004599A6h  call 00459934h
004599ABh  mov rsp, rbp
004599AEh  pop rbp
004599AFh  ret
;-

 - testInlined() contains only the delegate call. (call qword ptr 
[rax])
 - test() contains a call (call 00459934h) which contains 
the

   delegate call (call qword ptr [rax])

Actually i've even had to add (pragma inline false) to show the 
difference since DMD inlined automatically bar() in test().







Re: How to overload member function pointer and a regualr member function

2017-04-25 Thread Ali Çehreli via Digitalmars-d-learn

On 04/25/2017 11:54 AM, Ali Çehreli wrote:

> _Dmain:
> pushRBP
> movRBP,RSP
> subRSP,010h
> movRAX,_D6deneme4funcFifZv@GOTPCREL[RIP]
> mov-010h[RBP],RAX
> movssXMM0,FLAT:.rodata[00h][RIP]
> movss-8[RBP],XMM0
> leaRDX,_TMP0@PC32[RIP]
> movEDI,0Eh
> movRSI,RDX
> movssXMM0,-8[RBP]
> call  _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32
> movEAX,02Ah
> movssXMM1,FLAT:.rodata[00h][RIP]
> movss-4[RBP],XMM1
> movRDI,RAX
> movssXMM0,-4[RBP]
> callqword ptr -010h[RBP]
> xorEAX,EAX
> leave
> ret
> add[RAX],AL
> .text._Dmainends
>
> The call to jumbled writefln() is a direct call inside func():
>
> call  _D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32

My analysis is wrong because that writefln() is for the bar(float) 
overload but I still think what you want is achieved.


Ali



Re: How to overload member function pointer and a regualr member function

2017-04-25 Thread Ali Çehreli via Digitalmars-d-learn

On 04/25/2017 11:28 AM, ParticlePeter wrote:
> On Tuesday, 25 April 2017 at 16:27:43 UTC, Basile B. wrote:

>> with pragma(inline, true), the function body should be injected at the
>> call sites.
>
> This would not help I fear, the body of the function pointer is unknown
> in an external lib. I rather hoped that the compiler "sees" the
> parameter forwarding to the fp and is able to directly call it. Best
> thing would be for both overloads, but I would not know how to verify 
this.


pragma(inline, true) works because all you need inlined in this case is 
the body of bar(int, float). The compiler does call the function pointer 
directly.


import std.stdio;

struct Foo1
{
private void function(int,float) _bar;
void bar(float f) {
pragma(inline, true);
writefln("Called with %s", f);
}
void bar(int i, float f) {
pragma(inline, true);
_bar(i,f);
}
}

void func(int i, float f) {
writefln("Called with %s and %s", i, f);
}

void main() {
auto f = Foo1();
f.bar(1.5);
f.bar(42, 2.5);
}

Compile with -inline (and perhaps with -O):

  dmd -inline deneme.d

Generate the disassembly with obj2asm that comes with dmd (or with any 
other disassembly tool):


  obj2asm deneme.o > deneme.asm

You can open deneme.asm in an editor and search for function "_Dmain:" 
in it. Here is what my dmd 2.074 produced:


_Dmain:
pushRBP
mov RBP,RSP
sub RSP,010h
mov RAX,_D6deneme4funcFifZv@GOTPCREL[RIP]
mov -010h[RBP],RAX
movss   XMM0,FLAT:.rodata[00h][RIP]
movss   -8[RBP],XMM0
lea RDX,_TMP0@PC32[RIP]
mov EDI,0Eh
mov RSI,RDX
movss   XMM0,-8[RBP]
call  
_D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32
mov EAX,02Ah
movss   XMM1,FLAT:.rodata[00h][RIP]
movss   -4[RBP],XMM1
mov RDI,RAX
movss   XMM0,-4[RBP]
callqword ptr -010h[RBP]
xor EAX,EAX
leave
ret
add [RAX],AL
.text._Dmainends

The call to jumbled writefln() is a direct call inside func():

call  
_D3std5stdio17__T8writeflnTaTfZ8writeflnFNfxAafZv@PLT32

So, you're good... :)

Ali



Re: How to overload member function pointer and a regualr member function

2017-04-25 Thread ParticlePeter via Digitalmars-d-learn

On Tuesday, 25 April 2017 at 16:27:43 UTC, Basile B. wrote:

On Tuesday, 25 April 2017 at 15:43:48 UTC, ParticlePeter wrote:

On Tuesday, 25 April 2017 at 09:50:14 UTC, Basile B. wrote:

On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote:


Thanks for your reply, but that's what I would like to avoid, 
the additional indirection to call the function pointer with 
the original argument count.


Oops, i can believe i didn't read the last part of your 
question.


Do you have any idea about the likelihood of the compiler 
removing this indirection as an optimizations?


with pragma(inline, true), the function body should be injected 
at the call sites.


This would not help I fear, the body of the function pointer is 
unknown in an external lib. I rather hoped that the compiler 
"sees" the parameter forwarding to the fp and is able to directly 
call it. Best thing would be for both overloads, but I would not 
know how to verify this.


Re: How to overload member function pointer and a regualr member function

2017-04-25 Thread ParticlePeter via Digitalmars-d-learn

On Tuesday, 25 April 2017 at 09:50:14 UTC, Basile B. wrote:

On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote:

I would like to have this kind of struct:

struct Foo {
  private int i;
  void function( int i, float f ) bar;  // will be defined at 
runtime

  void bar( float f ) {
bar( i, f );
  }
}

[...]
How else can I get the required behavior?


Like this:

struct Foo1
{
private void function(int,float) _bar;
void bar(float){}
void bar(int i, float f){_bar(i,f);}
}


Thanks for your reply, but that's what I would like to avoid, the 
additional indirection to call the function pointer with the 
original argument count.
Do you have any idea about the likelihood of the compiler 
removing this indirection as an optimizations?


Re: How to overload member function pointer and a regualr member function

2017-04-25 Thread Basile B. via Digitalmars-d-learn

On Monday, 24 April 2017 at 16:46:21 UTC, ParticlePeter wrote:

I would like to have this kind of struct:

struct Foo {
  private int i;
  void function( int i, float f ) bar;  // will be defined at 
runtime

  void bar( float f ) {
bar( i, f );
  }
}

[...]
How else can I get the required behavior?


Like this:

struct Foo1
{
private void function(int,float) _bar;
void bar(float){}
void bar(int i, float f){_bar(i,f);}
}

Or like this:

struct Foo2
{
private void function(int,float) _bar;
void bar(float) {}
void function(int,float) bar() {return _bar;}
}


First solution looks better:

(new Foo2).bar()(0,0f) // less good
(new Foo1).bar(0,0f) // better




How to overload member function pointer and a regualr member function

2017-04-24 Thread ParticlePeter via Digitalmars-d-learn

I would like to have this kind of struct:

struct Foo {
  private int i;
  void function( int i, float f ) bar;  // will be defined at 
runtime

  void bar( float f ) {
bar( i, f );
  }
}

But apparently the function pointer and the member function 
cannot have the same name: Error: function main.Foo.bar conflicts 
with variable main.Foo.bar ...


I tried with an inner struct:
struct Foo {
  private int i;
  void function( int i, float f ) bar;  // will be defined at 
runtime

  private struct Inner {
void bar( float f ) {
  bar( i, f );
}
  }
  Inner inner;
}

But this time I get following error:
Error: need 'this' for 'i' of type 'int'

What does this message tell me? Should the inner struct not be 
able to access Foo.i?


How else can I get the required behavior?

I would prefer to avoid another indirection like this:
struct Foo {
  private int i;
  void function( int i, float f ) bar;  // will be defined at 
runtime

  void baz( float f ) {
bar( i, f );
  }
  void baz( int ii, float f ) {
bar( ii, f );
  }
}