refactor pointerBitmap()

This commit is contained in:
Walter Bright 2023-11-17 21:51:11 -08:00 committed by The Dlang Bot
parent f29a92dcbf
commit d1284d45b0
2 changed files with 35 additions and 27 deletions

View file

@ -36,6 +36,7 @@ import dmd.dstruct;
import dmd.dsymbol; import dmd.dsymbol;
import dmd.dtemplate; import dmd.dtemplate;
import dmd.errors; import dmd.errors;
import dmd.errorsink;
import dmd.expression; import dmd.expression;
import dmd.func; import dmd.func;
import dmd.globals; import dmd.globals;
@ -248,18 +249,18 @@ void write_instance_pointers(Type type, Symbol *s, uint offset)
return; return;
Array!(ulong) data; Array!(ulong) data;
ulong sz = getTypePointerBitmap(Loc.initial, type, &data); const ulong sz = getTypePointerBitmap(Loc.initial, type, data, global.errorSink);
if (sz == ulong.max) if (sz == ulong.max)
return; return;
const bytes_size_t = cast(size_t)Type.tsize_t.size(Loc.initial); const bytes_size_t = cast(size_t)Type.tsize_t.size(Loc.initial);
const bits_size_t = bytes_size_t * 8; const bits_size_t = bytes_size_t * 8;
auto words = cast(size_t)(sz / bytes_size_t); auto words = cast(size_t)(sz / bytes_size_t);
for (size_t i = 0; i < data.length; i++) foreach (i, const element; data[])
{ {
size_t bits = words < bits_size_t ? words : bits_size_t; size_t bits = words < bits_size_t ? words : bits_size_t;
for (size_t b = 0; b < bits; b++) foreach (size_t b; 0 .. bits)
if (data[i] & (1L << b)) if (element & (1L << b))
{ {
auto off = cast(uint) ((i * bits_size_t + b) * bytes_size_t); auto off = cast(uint) ((i * bits_size_t + b) * bytes_size_t);
objmod.write_pointerRef(s, off + offset); objmod.write_pointerRef(s, off + offset);

View file

@ -32,6 +32,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem; import dmd.dsymbolsem;
import dmd.dtemplate; import dmd.dtemplate;
import dmd.errors; import dmd.errors;
import dmd.errorsink;
import dmd.expression; import dmd.expression;
import dmd.expressionsem; import dmd.expressionsem;
import dmd.func; import dmd.func;
@ -92,44 +93,50 @@ private Dsymbol getDsymbolWithoutExpCtx(RootObject oarg)
} }
/** /**
* get an array of size_t values that indicate possible pointer words in memory * Fill an array of target size_t values that indicate possible pointer words in memory
* if interpreted as the type given as argument * if interpreted as the type given as argument.
* Returns: the size of the type in bytes, ulong.max on error * One bit in the array per pointer-sized piece of memory
* Params:
* loc = location for error messages
* t = type to generate pointer bitmap from
* data = array forming the bitmap
* eSink = error message sink
* Returns:
* size of the type `t` in bytes, ulong.max on error
*/ */
ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data) ulong getTypePointerBitmap(Loc loc, Type t, ref Array!(ulong) data, ErrorSink eSink)
{ {
ulong sz;
auto tc = t.isTypeClass(); auto tc = t.isTypeClass();
if (tc && !tc.sym.isInterfaceDeclaration()) const ulong sz = (tc && !tc.sym.isInterfaceDeclaration())
sz = tc.sym.AggregateDeclaration.size(loc); ? tc.sym.AggregateDeclaration.size(loc)
else : t.size(loc);
sz = t.size(loc);
if (sz == SIZE_INVALID) if (sz == SIZE_INVALID)
return ulong.max; return ulong.max;
const sz_size_t = Type.tsize_t.size(loc); const sz_size_t = Type.tsize_t.size(loc); // size of target's size_t
assert(sz_size_t <= ulong.sizeof);
if (sz > sz.max - sz_size_t) if (sz > sz.max - sz_size_t)
{ {
error(loc, "size overflow for type `%s`", t.toChars()); eSink.error(loc, "size overflow for type `%s`", t.toChars());
return ulong.max; return ulong.max;
} }
ulong bitsPerWord = sz_size_t * 8; const ulong bitsPerElement = sz_size_t * 8; // bits used in each array element
ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; const ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; // pointers have same size as sz_size_t
ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord; const ulong length = (cntptr + bitsPerElement - 1) / bitsPerElement; // a bit per pointer
data.setDim(cast(size_t)cntdata); data.setDim(cast(size_t)length);
data.zero(); data.zero();
ulong offset; ulong offset;
bool error; bool error; // sticky error indicator
void visit(Type t) void visit(Type t)
{ {
void setpointer(ulong off) void setpointer(ulong off)
{ {
ulong ptroff = off / sz_size_t; ulong ptroff = off / sz_size_t;
(*data)[cast(size_t)(ptroff / (8 * sz_size_t))] |= 1L << (ptroff % (8 * sz_size_t)); data[cast(size_t)(ptroff / bitsPerElement)] |= 1L << (ptroff % bitsPerElement);
} }
void visitType(Type t) void visitType(Type t)
@ -282,28 +289,28 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
* *
* Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...] * Returns: [T.sizeof, pointerbit0-31/63, pointerbit32/64-63/128, ...]
*/ */
private Expression pointerBitmap(TraitsExp e) private Expression pointerBitmap(TraitsExp e, ErrorSink eSink)
{ {
if (!e.args || e.args.length != 1) if (!e.args || e.args.length != 1)
{ {
error(e.loc, "a single type expected for trait pointerBitmap"); eSink.error(e.loc, "a single type expected for trait pointerBitmap");
return ErrorExp.get(); return ErrorExp.get();
} }
Type t = getType((*e.args)[0]); Type t = getType((*e.args)[0]);
if (!t) if (!t)
{ {
error(e.loc, "`%s` is not a type", (*e.args)[0].toChars()); eSink.error(e.loc, "`%s` is not a type", (*e.args)[0].toChars());
return ErrorExp.get(); return ErrorExp.get();
} }
Array!(ulong) data; Array!(ulong) data;
ulong sz = getTypePointerBitmap(e.loc, t, &data); const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink);
if (sz == ulong.max) if (sz == ulong.max)
return ErrorExp.get(); return ErrorExp.get();
auto exps = new Expressions(data.length + 1); auto exps = new Expressions(data.length + 1);
(*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); (*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t); // [0] is size in bytes of t
foreach (size_t i; 1 .. exps.length) foreach (size_t i; 1 .. exps.length)
(*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t); (*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t);
@ -1871,7 +1878,7 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
} }
if (e.ident == Id.getPointerBitmap) if (e.ident == Id.getPointerBitmap)
{ {
return pointerBitmap(e); return pointerBitmap(e, global.errorSink);
} }
if (e.ident == Id.initSymbol) if (e.ident == Id.initSymbol)
{ {