Simpler test case shows that it's nothing to do with tuples!
ICE on both D1 and D2.
struct Dog {
int q;
int r;
}
Dog hound(int y) {
return *cast(Dog*)(&y);
}
Comment #4 by clugdbug — 2009-10-07T06:31:19Z
Even simpler test case shows it's nothing to do with structs! It just happens when casting the last parameter, **which is passed in EAX, not on the stack**, to an 8-byte value -- either an 8-byte struct or a long/ulong.
Although this code is legal, it's surely a bug. It would be OK for the compiler to generate an error message.
long foo(int y) {
return *cast(long*)(&y);
}
Comment #5 by clugdbug — 2009-10-07T23:58:13Z
This seems to be a superficial ICE. It only happens in this wierd situation,
when a parameter, which was passed in a register, needs to be stored into a
double-register (EDX:EAX).
In this case, the existing register can't be re-used, even though it satisfies
all the conditions in cod1 line 3433.
We simply need to add an extra condition to prevent the register being
re-used.After this simple change, correct code is generated instead of the ICE.
I think this case never occurs in the calling conventions used in DMC.
Of course, taking the address of an parameter, then casting it to the wrong
size is a highly dubious thing
to be doing, since it's getting whatever happens to be on the stack. Unsafe
mode only!
PATCH (against DMD2.033) cod1.c, line 3434:
// See if we can use register that parameter was passed in
if (regcon.params && e->EV.sp.Vsym->Sclass == SCfastpar &&
- regcon.params & mask[e->EV.sp.Vsym->Spreg])
+ regcon.params & mask[e->EV.sp.Vsym->Spreg] && sz!=REGSIZE*2)
{ assert(sz <= REGSIZE);
reg = e->EV.sp.Vsym->Spreg;
forregs = mask[reg];
mfuncreg &= ~forregs;
regcon.used |= forregs;
return fixresult(e,forregs,pretregs);
}