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.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);
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue