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

View file

@ -32,6 +32,7 @@ import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.errorsink;
import dmd.expression;
import dmd.expressionsem;
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
* if interpreted as the type given as argument
* Returns: the size of the type in bytes, ulong.max on error
* Fill an array of target size_t values that indicate possible pointer words in memory
* if interpreted as the type given as argument.
* 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();
if (tc && !tc.sym.isInterfaceDeclaration())
sz = tc.sym.AggregateDeclaration.size(loc);
else
sz = t.size(loc);
const ulong sz = (tc && !tc.sym.isInterfaceDeclaration())
? tc.sym.AggregateDeclaration.size(loc)
: t.size(loc);
if (sz == SIZE_INVALID)
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)
{
error(loc, "size overflow for type `%s`", t.toChars());
eSink.error(loc, "size overflow for type `%s`", t.toChars());
return ulong.max;
}
ulong bitsPerWord = sz_size_t * 8;
ulong cntptr = (sz + sz_size_t - 1) / sz_size_t;
ulong cntdata = (cntptr + bitsPerWord - 1) / bitsPerWord;
const ulong bitsPerElement = sz_size_t * 8; // bits used in each array element
const ulong cntptr = (sz + sz_size_t - 1) / sz_size_t; // pointers have same size as sz_size_t
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();
ulong offset;
bool error;
bool error; // sticky error indicator
void visit(Type t)
{
void setpointer(ulong off)
{
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)
@ -282,28 +289,28 @@ ulong getTypePointerBitmap(Loc loc, Type t, Array!(ulong)* data)
*
* 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)
{
error(e.loc, "a single type expected for trait pointerBitmap");
eSink.error(e.loc, "a single type expected for trait pointerBitmap");
return ErrorExp.get();
}
Type t = getType((*e.args)[0]);
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();
}
Array!(ulong) data;
ulong sz = getTypePointerBitmap(e.loc, t, &data);
const ulong sz = getTypePointerBitmap(e.loc, t, data, eSink);
if (sz == ulong.max)
return ErrorExp.get();
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)
(*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)
{
return pointerBitmap(e);
return pointerBitmap(e, global.errorSink);
}
if (e.ident == Id.initSymbol)
{