From 27b891c0d810d1fcf88ff5e702e9d049232e8f8d Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Thu, 23 Nov 2023 23:13:43 +0100 Subject: [PATCH 1/3] core.cpuid: Fix div-by-zero on AMD CPUs with 256 (physical?) cores See: https://en.wikipedia.org/wiki/CPUID#EAX=80000008h:_Virtual_and_Physical_address_Sizes This *might* fix Issue 24254, although I'd expect the read value for that CPU to be 127 (*physical* cores minus 1), not the problematic 255. --- druntime/src/core/cpuid.d | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/druntime/src/core/cpuid.d b/druntime/src/core/cpuid.d index 9c5735728b..62edbac34f 100644 --- a/druntime/src/core/cpuid.d +++ b/druntime/src/core/cpuid.d @@ -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; } From e1197fc765d0b94470a96f8655e9e2d7d8267a66 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sat, 25 Nov 2023 13:45:30 -0800 Subject: [PATCH 2/3] fix Issue 24257 - ImportC: ICE on accessing last _Bool bitfield (#15861) --- compiler/src/dmd/e2ir.d | 34 ++++++++++++++++++++++++----- compiler/test/runnable/dbitfields.d | 34 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index b8c99e6ef1..63eba003c7 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -3096,16 +3096,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) @@ -6561,6 +6581,8 @@ elem *toElemStructLit(StructLiteralExp sle, ref IRState irs, EXP op, Symbol *sym { // 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); e1 = el_bin(OPbit, e1.Ety, e1, mos); } } diff --git a/compiler/test/runnable/dbitfields.d b/compiler/test/runnable/dbitfields.d index 0d1877a7bf..aa154c7bbb 100644 --- a/compiler/test/runnable/dbitfields.d +++ b/compiler/test/runnable/dbitfields.d @@ -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() @@ -184,6 +217,7 @@ int main() test5(); test6(); test7(); + test24257(); return 0; } From ec34292ead8bb30bae9f779326c0931238c70e75 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Sun, 26 Nov 2023 02:52:07 -0800 Subject: [PATCH 3/3] fix Issue 24262 - Assert error with bit fields (#15864) --- compiler/src/dmd/e2ir.d | 59 +++++++++++++++++++++--------- compiler/test/runnable/bitfields.c | 29 +++++++++++++++ 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index 63eba003c7..8b118676e0 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -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) @@ -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); } } diff --git a/compiler/test/runnable/bitfields.c b/compiler/test/runnable/bitfields.c index 8946c83257..20ff397a90 100644 --- a/compiler/test/runnable/bitfields.c +++ b/compiler/test/runnable/bitfields.c @@ -254,6 +254,34 @@ _Static_assert(test7s2() == -2, "3"); /******************************************/ +// https://issues.dlang.org/show_bug.cgi?id=24257 + +#include + +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(); @@ -263,6 +291,7 @@ int main() test5(); test6(); test7(); + test24257(); return 0; }