Am 07.03.2013 22:19, schrieb Walter Bright:
Oops, I missed that. It's a bug in dmd.

OK, this explains the inconsistency between normal and varargs functions.

nevertheless the non-POD is passed in registers. Add a __traits(isPOD, Date) test to the example, it returns false.


I also don't understand how a copy ctor could break this.

Because a copy ctor executes arbitrary code, and this just does not work in the general case if a value is in a register.

Yes, the struct value can't be passed _to the copy constructor_ in a register - but the copy ctor itself is always called with a reference to the value, i.e. it's declared as
__copyctor(ref Date this, ref Date b)

For all other functions I don't see why it can't be passed in a register.


The copy constructor must have its address. Registers don't have an address.
Yes, registers don't have an address. But think of passing in a registers as a "move", not as a copy and moving the value out of that register in the callee again:

TDPL, page 249:
"First off, D objects must be relocatable, that is location-independent: an object can be moved around memory be using raw memory move without it's integrity being affected. [...] It is illegal to create objects with internal pointers in D and the compiler and runtime subsystem are free to assume observance of this rule. [...] The postblit constructor makes copying equivalent to a move plus an optional user-defined hook [...]. The compiler is free to not insert the call to this(this) whenever it can prove the source of the copy will not be used after the copying process".

So C++ would probably pass a non-POD like this:

;-0x8(%ebp) is the local value
------------
mov -0x8(%ebp),-0x4(%ebp) ;create the copy for the callee function lea -0x4(%ebp),%eax ;load address of copy
call   <_D1e4Date8__cpctorMxFKxS1e4DateZv>  ;call copy ctor for copy
lea -0x4(%ebp),%eax ;load address of copy
call <function> ;call function, passing a _reference_ to copy

<function>
(%eax)                           ;do something with object pointed to by eax
------------

And this is how it can be done when passing by value in a register

;-0x8(%ebp) is the local value
------------
mov -0x8(%ebp),-0x4(%ebp) ;create the copy for the callee function lea -0x4(%ebp),%eax ;load address of copy
call   <_D1e4Date8__cpctorMxFKxS1e4DateZv>  ;call copy ctor for copy
mov -0x4(%ebp),%eax ;load _value_ of copy (move copy into eax) *
call <function> ;call function, passing a _value_

<function>
mov %eax,-0x4(%ebp) ;load the value passed in the register back onto stack
;(move copy from eax to stack) *
-0x4(%ebp) ;do something with object
------------

So why is the second example illegal? In the end in both examples we have a valid address as the value is moved out of the register again, so everything which can be done in the first example can be done in the second example. I only see 2 differences between those two examples: * The second example has two additional memory moves (or bitblits). But it never accesses the original value again after a move, so according to TDPL this is legal and there is no need to call the copy ctor for these bit blits(moves).

* Because of the moves in the second example the address passed to the copy ctor call is different from the address <function> sees. This is why C++ can't do #2, as in C++ the address must be the same. TDPL explicitly states that moves and changing addresses is allowed in D, so this is not an issue.

So please explain what's illegal in this concrete example #2.

--
Johannes Pfau

_______________________________________________
dmd-internals mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/dmd-internals

Reply via email to