Skip to content

Commit

Permalink
Merge pull request #15865 from dlang/stable
Browse files Browse the repository at this point in the history
Merge stable into master
  • Loading branch information
dkorpel authored Nov 26, 2023
2 parents 1642660 + ec34292 commit 41f3577
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 25 deletions.
89 changes: 67 additions & 22 deletions compiler/src/dmd/e2ir.d
Original file line number Diff line number Diff line change
Expand Up @@ -3067,16 +3067,36 @@ elem* toElem(Expression e, ref IRState irs)
e = addressElem(e, tb1);
typ = tybasic(e.Ety);
}
auto offset = el_long(TYsize_t, v.offset);
offset = objc.getOffset(v, tb1, offset);
e = el_bin(OPadd, typ, e, offset);

const tym = totym(dve.type);
auto voffset = v.offset;
uint bitfieldarg = 0;
auto bf = v.isBitFieldDeclaration();
if (bf)
{
// adjust bit offset for bitfield so the type tym encloses the bitfield
const szbits = tysize(tym) * 8;
auto bitOffset = bf.bitOffset;
if (bitOffset + bf.fieldWidth > szbits)
{
const advance = bf.bitOffset / szbits;
voffset += advance;
bitOffset -= advance * 8;
assert(bitOffset + bf.fieldWidth <= szbits);
}
//printf("voffset %u bitOffset %u fieldWidth %u bits %u\n", cast(uint)voffset, bitOffset, bf.fieldWidth, szbits);
bitfieldarg = bf.fieldWidth * 256 + bitOffset;
}

auto eoffset = el_long(TYsize_t, voffset);
e = el_bin(OPadd, typ, e, objc.getOffset(v, tb1, eoffset));
if (v.storage_class & (STC.out_ | STC.ref_))
e = el_una(OPind, TYnptr, e);
e = el_una(OPind, totym(dve.type), e);
if (auto bf = v.isBitFieldDeclaration())
e = el_una(OPind, tym, e);
if (bf)
{
// Insert special bitfield operator
auto mos = el_long(TYuint, bf.fieldWidth * 256 + bf.bitOffset);
auto mos = el_long(TYuint, bitfieldarg);
e = el_bin(OPbit, e.Ety, e, mos);
}
if (tybasic(e.Ety) == TYstruct)
Expand Down Expand Up @@ -6474,13 +6494,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 @@ -6491,48 +6511,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
{
//printf("2bitOffset %u fieldWidth %u bits %u\n", bf.bitOffset, bf.fieldWidth, tysize(e1.Ety) * 8);
// Insert special bitfield operator
auto mos = el_long(TYuint, bf.fieldWidth * 256 + bf.bitOffset);
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;
}
34 changes: 34 additions & 0 deletions compiler/test/runnable/dbitfields.d
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,39 @@ static assert(test7u() == 1);
static assert(test7s() == -1);
static assert(test7s2() == -2);

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

struct S24257
{
uint : 15;
bool done : 1;
}

bool advance()
{
S24257 n;
n.done = false;
n.done = true;
return n.done;
}

bool retard()
{
S24257 n;
n.done = true;
n.done = false;
return n.done;
}

static assert(advance() == true);

void test24257()
{
assert(advance() == true);
assert(retard() == false);
}

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

int main()
Expand All @@ -184,6 +217,7 @@ int main()
test5();
test6();
test7();
test24257();

return 0;
}
7 changes: 4 additions & 3 deletions druntime/src/core/cpuid.d
Original file line number Diff line number Diff line change
Expand Up @@ -628,16 +628,17 @@ void getAMDcacheinfo()

if (max_extended_cpuid >= 0x8000_0006) {
// AMD K6-III or K6-2+ or later.
ubyte numcores = 1;
uint numcores = 1;
if (max_extended_cpuid >= 0x8000_0008) {
// read the number of physical cores (minus 1) from the 8 lowest ECX bits
version (GNU_OR_LDC) asm pure nothrow @nogc {
"cpuid" : "=a" (dummy), "=c" (numcores) : "a" (0x8000_0008) : "ebx", "edx";
} else asm pure nothrow @nogc {
mov EAX, 0x8000_0008;
cpuid;
mov numcores, CL;
mov numcores, ECX;
}
++numcores;
numcores = (numcores & 0xFF) + 1;
if (numcores>cpuFeatures.maxCores) cpuFeatures.maxCores = numcores;
}

Expand Down

0 comments on commit 41f3577

Please sign in to comment.