Useless bit of code, but it shouldn't ICE. Internal error: ..\ztc\cod1.c 3282 ----------- struct Dog(B...) { B values; static Dog!(B) create(B x) { return *cast(Dog!(B)*)(&x[1]); } } void main() { auto c = Dog!(int, int).create(7,4); }
*** Bug 1139 has been marked as a duplicate of this bug. ***
Added to DStress as http://dstress.kuehne.cn/run/t/template_struct_09_A.d http://dstress.kuehne.cn/run/t/template_struct_09_B.d http://dstress.kuehne.cn/run/t/template_struct_09_C.d
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); }
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); }
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); }
Fixed dmd 1.049 and 2.034