Bug 9720 – OSX wrong code with -O Illegal instruction
Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Mac OS X
Creation time
2013-03-14T07:12:00Z
Last change time
2015-06-09T05:11:51Z
Keywords
wrong-code
Assigned to
nobody
Creator
monarchdodra
Comments
Comment #0 by monarchdodra — 2013-03-14T07:12:20Z
Investigated from:
https://github.com/D-Programming-Language/phobos/pull/878http://d.puremagic.com/test-results/pull-history.ghtml?projectid=1&repoid=3&pullid=878
Happens with OSX, when compile with -O.
Below a reduced test case:
//----
import std.stdio;
//Simplified RefCounted
struct MyRef(T)
{
private struct Impl
{
T _payload;
size_t _count;
}
Impl* _store;
this(int i)
{
_store = new Impl;
_store._payload = T.init;
_store._count = 1;
}
~this()
{
if (!_store) return;
writeln("d: ", _store._count); //Comment me
--_store._count;
}
}
//Extracted from Array
struct Payload
{
size_t _capacity; //Comment me
int[] _pay; //Comment me
size_t insertBack(Stuff)(Stuff /+stuff+/)
{
immutable newLen = _pay.length + 3;
_pay.length = newLen;
_pay = _pay[0 .. newLen]; //Comment me
return 3;
}
}
alias Data = MyRef!Payload;
unittest
{
auto a = Data(1);
auto b = Data(1);
writeln(__LINE__);
a._store._payload.insertBack(1); //Passes
writeln(__LINE__);
a._store._payload.insertBack(b); //Fails
writeln(__LINE__);
}
//----
rdmd -w -d -property -O --main -unittest test2.d
47
49
d: 1
Illegal instruction
//---
I was not able to simplify much more, as the compile-time behavior is non deterministic: EG: removing an unused variable such as "capacity" is enough to make the problem "disappear" (or at least, unobservable).
AFAIK, this code contains nothing unsafe, and the only requirement to reproduce is as simple as "pass by value something with a destructor"... (!)
Comment #1 by bugzilla — 2013-04-01T19:19:59Z
64 bit only.
Comment #2 by bugzilla — 2013-04-01T21:11:59Z
Reduced test case:
------------------
import core.stdc.stdio;
struct Payload
{
size_t _capacity; //Comment me
int[] _pay; //Comment me
size_t insertBack(Data d)
{
immutable newLen = _pay.length + 3;
_pay.length = newLen;
_pay = _pay[0 .. newLen]; //Comment me
return 3;
}
}
struct Impl
{
Payload _payload;
size_t _count;
}
struct Data
{
Impl* _store;
this(int i)
{
_store = new Impl;
_store._payload = Payload.init;
}
~this()
{
printf("%d\n", _store._count);
--_store._count;
}
}
void main()
{
auto a = Data(1);
auto b = Data(1);
a._store._payload.insertBack(b); //Fails
}