On Friday, 7 March 2014 at 04:01:15 UTC, Adam D. Ruppe wrote:
BTW you know what would help this? A pragma we can attach to a struct which makes it a very thin value type.

pragma(thin_struct)
struct A {
   int a;
   int foo() { return a; }
   static A get() { A(10); }
}

void test() {
    A a = A.get();
    printf("%d", a.foo());
}

With the pragma, A would be completely indistinguishable from int in all ways.

What do I mean?
$ dmd -release -O -inline test56 -c

Let's look at A.foo:

A.foo:
   0:   55                      push   ebp
   1:   8b ec                   mov    ebp,esp
   3:   50                      push   eax
4: 8b 00 mov eax,DWORD PTR [eax] ; waste!
   6:   8b e5                   mov    esp,ebp
   8:   5d                      pop    ebp
   9:   c3                      ret


It is line four that bugs me: the struct is passed as a *pointer*, but its only contents are an int, which could just as well be passed as a value. Let's compare it to an identical function in operation:

int identity(int a) { return a; }

00000000 <_D6test568identityFiZi>:
   0:   55                      push   ebp
   1:   8b ec                   mov    ebp,esp
   3:   83 ec 04                sub    esp,0x4
   6:   c9                      leave
   7:   c3                      ret

lol it *still* wastes time, setting up a stack frame for nothing. But we could just as well write asm { naked; ret; } and it would work as expected: the argument is passed in EAX and the return value is expected in EAX. The function doesn't actually have to do anything.

struct A {
   int a;
   //int foo() { return a; }
   static A get() { A(10); }
}

int foo(A a) { return a.a; }

printf("%d", a.foo());

Now it's passed by value.

Though, I needed checked arithmetic only twice: for cast from long to int and for cast from double to long. If you expect your number type to overflow, you probably chose wrong type.

Reply via email to