Skip to content

Commit 7f18b71

Browse files
authored
fix github Issue 18247 Bitfield with 64 bits always zero (dlang#21653)
1 parent 62d35c8 commit 7f18b71

2 files changed

Lines changed: 36 additions & 5 deletions

File tree

compiler/src/dmd/backend/cgelem.d

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3218,16 +3218,20 @@ L1:
32183218
@trusted
32193219
private elem* elbit(elem* e, Goal goal)
32203220
{
3221+
//printf("elbit()\n");
3222+
//elem_print(e);
32213223
tym_t tym1 = e.E1.Ety;
32223224
uint sz = tysize(tym1) * 8;
32233225
elem* e2 = e.E2;
32243226
uint wb = e2.Vuns;
32253227

32263228
uint w = (wb >> 8) & 0xFF; // width in bits of field
3227-
targ_ullong m = (cast(targ_ullong)1 << w) - 1; // mask w bits wide
3229+
ulong m = (cast(ulong)1 << w) - 1; // mask w bits wide
3230+
if (w == 64) // undefined behavior
3231+
m = ~0L; // fix it
32283232
uint b = wb & 0xFF; // bits to right of field
32293233
uint c = 0;
3230-
//printf("w %u + b %u <= sz %u\n", w, b, sz);
3234+
//printf("wb x%x w x%x + b x%x <= sz x%x\n", wb, w, b, sz);
32313235
assert(w + b <= sz);
32323236

32333237
if (tyuns(tym1)) // if uint bit field
@@ -4055,13 +4059,17 @@ static if (0) // Doesn't work too well, removed
40554059
if (e1.E1.Eoper == OPcomma || OTassign(e1.E1.Eoper))
40564060
return cgel_lvalue(e);
40574061

4062+
//printf("elbitassign()\n");
4063+
//elem_print(e);
40584064
uint t = e.Ety;
40594065
elem* l = e1.E1; // lvalue
40604066
elem* r = e.E2;
40614067
tym_t tyl = l.Ety;
40624068
uint sz = tysize(tyl) * 8;
40634069
uint w = (e1.E2.Vuns >> 8); // width in bits of field
4064-
targ_ullong m = (cast(targ_ullong)1 << w) - 1; // mask w bits wide
4070+
ulong m = (cast(ulong)1 << w) - 1; // mask w bits wide
4071+
if (w == 64) // undefined behavior
4072+
m = ~0L; // fix it
40654073
uint b = e1.E2.Vuns & 0xFF; // bits to shift
40664074

40674075
elem* l2;
@@ -4163,6 +4171,8 @@ private elem* elopass(elem* e, Goal goal)
41634171
Goal wantres = goal;
41644172
if (e1.Eoper == OPbit)
41654173
{
4174+
//printf("OPbitass()\n");
4175+
//elem_print(e);
41664176
const op = opeqtoop(e.Eoper);
41674177

41684178
// Make sure t is uint
@@ -4174,8 +4184,11 @@ private elem* elopass(elem* e, Goal goal)
41744184
tym_t tyl = l.Ety;
41754185
elem* r = e.E2;
41764186
uint w = (e1.E2.Vuns >> 8) & 0xFF; // width in bits of field
4177-
targ_llong m = (cast(targ_llong)1 << w) - 1; // mask w bits wide
4187+
ulong m = (cast(ulong)1 << w) - 1; // mask w bits wide
4188+
if (w == 64) // undefined behavior
4189+
m = ~0L; // fix it
41784190
uint b = e1.E2.Vuns & 0xFF; // bits to shift
4191+
//printf("m x%llx w x%x + b x%x <= sz x%x\n", m, w, b, tysize(tyl) * 8);
41794192

41804193
elem* l2,l3,op2,eres;
41814194

@@ -4331,7 +4344,9 @@ private elem* elpost(elem* e, Goal goal)
43314344
targ_llong r = el_tolong(e.E2);
43324345

43334346
uint w = (e1.E2.Vuns >> 8) & 0xFF; // width in bits of field
4334-
targ_llong m = (cast(targ_llong)1 << w) - 1; // mask w bits wide
4347+
ulong m = (cast(ulong)1 << w) - 1; // mask w bits wide
4348+
if (w == 64) // undefined behavior
4349+
m = ~0L; // fix it
43354350

43364351
tym_t ty = e.Ety;
43374352
if (e.Eoper != OPpostinc)

compiler/test/runnable/bit.d

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,28 @@ void test3()
9595
assert(__traits(getMember, u, "b") == 2);
9696
}
9797

98+
/********************************************/
99+
// https://github.com/dlang/dmd/issues/18247
100+
101+
struct S4
102+
{
103+
ulong a:64;
104+
}
105+
106+
void test4()
107+
{
108+
S4 s;
109+
s.a = 1;
110+
assert(s.a == 1);
111+
}
112+
98113
/********************************************/
99114

100115
int main()
101116
{
102117
test1();
103118
test2();
104119
test3();
120+
test4();
105121
return 0;
106122
}

0 commit comments

Comments
 (0)