Skip to content

Commit

Permalink
fix Issue 24262 - Assert error with bit fields (#15864)
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright authored Nov 26, 2023
1 parent e1197fc commit ec34292
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 18 deletions.
59 changes: 41 additions & 18 deletions compiler/src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -6522,13 +6522,13 @@ elem *toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol *sym
// CTFE may fill the hidden pointer by NullExp.
{
VarDeclaration vbf;
foreach (i, el; *sle.elements)
foreach (i, element; *sle.elements)
{
if (!el)
if (!element)
continue;

VarDeclaration v = sle.sd.fields[i];
assert(!v.isThisDeclaration() || el.op == EXP.null_);
assert(!v.isThisDeclaration() || element.op == EXP.null_);

elem *e1;
if (tybasic(stmp.Stype.Tty) == TYnptr)
Expand All @@ -6539,50 +6539,73 @@ elem *toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol *sym
{
e1 = el_ptr(stmp);
}
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));

elem *ep = toElem(el, irs);
elem *ep = toElem(element, irs);

Type t1b = v.type.toBasetype();
Type t2b = el.type.toBasetype();
Type t2b = element.type.toBasetype();
if (t1b.ty == Tsarray)
{
e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));
if (t2b.implicitConvTo(t1b))
{
elem *esize = el_long(TYsize_t, t1b.size());
ep = array_toPtr(el.type, ep);
ep = array_toPtr(element.type, ep);
e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
}
else
{
elem *edim = el_long(TYsize_t, t1b.size() / t2b.size());
e1 = setArray(el, e1, edim, t2b, ep, irs, op == EXP.construct ? EXP.blit : op);
e1 = setArray(element, e1, edim, t2b, ep, irs, op == EXP.construct ? EXP.blit : op);
}
}
else
{
tym_t ty = totym(v.type);
e1 = el_una(OPind, ty, e1);
if (tybasic(ty) == TYstruct)
const tym_t tym = totym(v.type);
auto voffset = v.offset;
uint bitfieldArg;
uint bitOffset;
auto bf = v.isBitFieldDeclaration();
if (bf)
{
const szbits = tysize(tym) * 8;
bitOffset = bf.bitOffset;
if (bitOffset + bf.fieldWidth > szbits)
{
const advance = bitOffset / szbits;
voffset += advance;
bitOffset -= advance * 8;
assert(bitOffset + bf.fieldWidth <= szbits);
}
bitfieldArg = bf.fieldWidth * 256 + bitOffset;

//printf("2bitOffset %u fieldWidth %u bits %u\n", bitOffset, bf.fieldWidth, szbits);
assert(bitOffset + bf.fieldWidth <= szbits);
}

e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, voffset));
e1 = el_una(OPind, tym, e1);
if (tybasic(tym) == TYstruct)
{
e1.ET = Type_toCtype(v.type);
if (auto bf = v.isBitFieldDeclaration())
assert(!bf);
}
if (bf)
{
if (!vbf || vbf.offset + vbf.type.size() <= v.offset)
{
/* Initialize entire location the bitfield is in
* ep = (ep & ((1 << bf.fieldWidth) - 1)) << bf.bitOffset
*/
tym_t e1ty = e1.Ety;
auto ex = el_bin(OPand, e1ty, ep, el_long(e1ty, (1L << bf.fieldWidth) - 1));
ep = el_bin(OPshl, e1ty, ex, el_long(e1ty, bf.bitOffset));
auto ex = el_bin(OPand, tym, ep, el_long(tym, (1L << bf.fieldWidth) - 1));
ep = el_bin(OPshl, tym, ex, el_long(tym, bitOffset));
vbf = v;
}
else
{
// Insert special bitfield operator
auto mos = el_long(TYuint, bf.fieldWidth * 256 + bf.bitOffset);
//printf("2bitOffset %u fieldWidth %u bits %u\n", bf.bitOffset, bf.fieldWidth, tysize(e1.Ety) * 8);
assert(bf.bitOffset + bf.fieldWidth <= tysize(e1.Ety) * 8);
// Insert special bitfield operator
auto mos = el_long(TYuint, bitfieldArg);
e1 = el_bin(OPbit, e1.Ety, e1, mos);
}
}
Expand Down
29 changes: 29 additions & 0 deletions compiler/test/runnable/bitfields.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,34 @@ _Static_assert(test7s2() == -2, "3");

/******************************************/

// https://issues.dlang.org/show_bug.cgi?id=24257

#include <assert.h>

struct Entry
{
unsigned id : 15;
_Bool done : 1;
};

struct State
{
struct Entry e;
};

void test24257()
{
int i = 72;
struct State s = (struct State){i};
if (s.e.id != 72)
{
printf("error %d\n", __LINE__);
exit(1);
}
}

/******************************************/

int main()
{
test1();
Expand All @@ -263,6 +291,7 @@ int main()
test5();
test6();
test7();
test24257();

return 0;
}

0 comments on commit ec34292

Please sign in to comment.