mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
refactor pointerBitmap()
This commit is contained in:
parent
f29a92dcbf
commit
d1284d45b0
2 changed files with 35 additions and 27 deletions
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue