Spin-off from issue 18717 which can be closed as a duplicate when this one gets fixed.
----
void main()
{
enum bitsPerSizeT = size_t.sizeof * 8;
enum bitIndex = int.max + 1L;
auto a = new size_t[](bitIndex / bitsPerSizeT + 1);
bt(a.ptr, bitIndex);
}
/* Copied from core.bitop. */
int bt(in size_t* p, size_t bitnum) pure @system
{
static if (size_t.sizeof == 8)
return ((p[bitnum >> 6] & (1L << (bitnum & 63)))) != 0;
else static if (size_t.sizeof == 4)
return ((p[bitnum >> 5] & (1 << (bitnum & 31)))) != 0;
else
static assert(0);
}
----
Compile with `-O`. Resulting program segfaults.
Generated code for the bt function:
----
0: 55 push rbp
1: 48 8b ec mov rbp,rsp
4: 0f a3 3e bt DWORD PTR [rsi],edi
7: 19 c0 sbb eax,eax
9: f7 d8 neg eax
b: 5d pop rbp
c: c3 ret
----
edi should be rdi in the bt instruction.
It's hard to find information on this, but this page says that bt interprets the offset as signed: <http://faydoc.tripod.com/cpu/bt.htm>. That explains the segfault, even though `bitIndex` fits into a uint.
Comment #1 by ketmar — 2018-04-05T15:45:14Z
it segfaults on x86 too. but i won't change "hardware" field, 'cause it seems that with x86_64 there is a codegen bug too, and fixing segfault for x86_64 should automatically fix it for x86.
(In reply to Ketmar Dark from comment #1)
> it segfaults on x86 too. but i won't change "hardware" field, 'cause it
> seems that with x86_64 there is a codegen bug too, and fixing segfault for
> x86_64 should automatically fix it for x86.
I think we can split this in two:
1) Fix the x86-64 issue presented here by fixing the register size. This is the easy part. It doesn't fix the situation on x86.
2) File a new issue for the larger problem: core.bitop.bt's bitnum parameter is a size_t when it should be a ptrdiff_t. Then bt's body has to be adjusted for that, because D doesn't have negatives indices. And dmd has to be adjusted to recognize the new body.
Comment #4 by ketmar — 2018-04-05T19:33:23Z
yeah. would you do it, please?
Comment #5 by ag0aep6g — 2018-04-05T21:23:31Z
(In reply to ag0aep6g from comment #3)
> 2) File a new issue for the larger problem: core.bitop.bt's bitnum parameter
> is a size_t when it should be a ptrdiff_t. Then bt's body has to be adjusted
> for that, because D doesn't have negatives indices. And dmd has to be
> adjusted to recognize the new body.
Filed that as issue 18734.