D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 14587 - [REG2.064] generated 64 bit code for switch jump tables is wrong
Summary: [REG2.064] generated 64 bit code for switch jump tables is wrong
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 All
: P1 regression
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2015-05-15 13:08 UTC by Rob Pieké
Modified: 2017-07-01 11:33 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Rob Pieké 2015-05-15 13:08:02 UTC
(reporting as an issue - suggested by John Colvin)

I'm consistently getting "Segmentation fault: 11" (dmd 2.067.1, OSX) on the code below.

I can't figure out where things are going wrong, because any attempt I make to debug via extra print statements causes the program to run successfully. Same if I try to compile with "-gc" ... it suddenly starts working, so I can't debug with gdb. And the code similarly seems to work fine with ldc2.

Many thanks in advance!

* * *

import std.stdio;

enum Suit {
	HEARTS, DIAMONDS, CLUBS, SPADES
}

enum Value {
	ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, 
JACK, QUEEN, KING
}

struct Card {
	Value value;
	Suit suit;
}

void printCard(in Card card) {
	final switch(card.value) {
		case Value.ACE:
			write("A");
			break;
		case Value.TWO, Value.THREE, Value.FOUR, Value.FIVE, Value.SIX, 
Value.SEVEN, Value.EIGHT, Value.NINE, Value.TEN:
			writef("%d", card.value);
			break;
		case Value.JACK:
			write("J");
			break;
		case Value.QUEEN:
			write("Q");
			break;
		case Value.KING:
			write("K");
			break;
	}
	final switch(card.suit) {
		case Suit.HEARTS:
			write("♡");
			break;
		case Suit.DIAMONDS:
			write("♢");
			break;
		case Suit.CLUBS:
			write("♣");
			break;
		case Suit.SPADES:
			write("♠");
			break;
	}
	write("\n");
}

int main() {
	auto card = Card(Value.JACK, Suit.CLUBS);
	printCard(card);
	return 0;
}
Comment 1 Steven Schveighoffer 2015-05-15 13:49:31 UTC
A reduced version:

struct Card {
    int value;
    int suit;
}

void foo(Card card) {
    switch(card.value) {
    case 4: case 5: case 6: case 11:
        break;
    default:
    }
}

void main() {
    auto card = Card(11, 1);
    foo(card);
} 

Changing anything at this point seems to make it run properly.
Comment 2 Rob Pieké 2015-05-15 16:14:32 UTC
Thanks for reducing it Steven!

I also did a bit more leg-work. It could be coincidence, but the code seems to work in DMD 2.063.2 and below and fails in 2.064 and above.

Not only OSX. Linux (64-bit) at a minimum as well.
Comment 3 Marc Schütz 2015-05-15 16:25:53 UTC
FWIW, I can reproduce it with DMD master on Linux x86_64. Interestingly, compiling with debug info makes the SEGV go away.
Comment 4 Marc Schütz 2015-05-15 16:36:06 UTC
It crashes upon entering the jump table:

(gdb) disas
Dump of assembler code for function _D2xx3fooFS2xx4CardZv:
   0x000000000041c7b0 <+0>:	push   %rbp
   0x000000000041c7b1 <+1>:	mov    %rsp,%rbp
   0x000000000041c7b4 <+4>:	sub    $0x10,%rsp
   0x000000000041c7b8 <+8>:	mov    %rdi,-0x8(%rbp)
   0x000000000041c7bc <+12>:	cmp    $0xb,%edi
   0x000000000041c7bf <+15>:	ja     0x41c7c8 <_D2xx3fooFS2xx4CardZv+24>
=> 0x000000000041c7c1 <+17>:	jmpq   *0x4374f8(,%rdi,8)
   0x000000000041c7c8 <+24>:	leaveq 
   0x000000000041c7c9 <+25>:	retq   

(gdb) print $edi
$1 = 11
(gdb) print $rdi
$2 = 4294967307

As you can see, %edi contains the correct offset, but it uses %rdi as an index. Most likely a bug in the code generator.
Comment 5 Vladimir Panteleev 2015-05-17 05:42:26 UTC
Introduced in https://github.com/D-Programming-Language/dmd/pull/2315
Comment 6 Walter Bright 2015-05-17 16:37:01 UTC
Great job, everyone, in tracking this one down. You guys have nailed it. It's critical. I'll work on a fix.
Comment 8 github-bugzilla 2015-05-17 20:28:07 UTC
Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/4f779561f89e12ff45e30996ad3c8217eb7522e2
fix Issue 14587 - DMD 2.067.1 generating crashing binary on OSX

https://github.com/D-Programming-Language/dmd/commit/a7d1edb3c17282994c53fdc797dc3d15f3919d68
Merge pull request #4666 from WalterBright/fix14587

fix Issue 14587 - generated 64 bit code for switch jump tables is wrong
Comment 9 github-bugzilla 2015-05-17 20:39:51 UTC
Commit pushed to dmd-1.x at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/51185a88a63762c5347b729e26ab9540c34201da
Merge pull request #4666 from WalterBright/fix14587

fix Issue 14587 - generated 64 bit code for switch jump tables is wrong
Comment 10 Steven Schveighoffer 2015-05-18 12:38:48 UTC
Awesome! Nice work everyone.
Comment 11 Rob Pieké 2015-05-18 13:32:17 UTC
Wow ... that was a productive weekend! Looking forward to this working its way into a future homebrew update! :D
Comment 12 github-bugzilla 2015-06-17 21:05:15 UTC
Commits pushed to stable at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/4f779561f89e12ff45e30996ad3c8217eb7522e2
fix Issue 14587 - DMD 2.067.1 generating crashing binary on OSX

https://github.com/D-Programming-Language/dmd/commit/a7d1edb3c17282994c53fdc797dc3d15f3919d68
Merge pull request #4666 from WalterBright/fix14587