Skip to content

Commit

Permalink
move determineSize/finalizeSize to dsymbolsem.d
Browse files Browse the repository at this point in the history
  • Loading branch information
thewilsonator committed Oct 6, 2024
1 parent 2024098 commit dd0f71d
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 297 deletions.
60 changes: 0 additions & 60 deletions compiler/src/dmd/aggregate.d
Original file line number Diff line number Diff line change
Expand Up @@ -187,66 +187,6 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
return fields.length - isNested() - (vthis2 !is null);
}

/***************************************
* Collect all instance fields, then determine instance size.
* Returns:
* false if failed to determine the size.
*/
extern (D) final bool determineSize(const ref Loc loc)
{
//printf("AggregateDeclaration::determineSize() %s, sizeok = %d\n", toChars(), sizeok);

// The previous instance size finalizing had:
if (type.ty == Terror || errors)
return false; // failed already
if (sizeok == Sizeok.done)
return true; // succeeded

if (!members)
{
.error(loc, "%s `%s` unknown size", kind, toPrettyChars);
return false;
}

if (_scope)
dsymbolSemantic(this, null);

// Determine the instance size of base class first.
if (auto cd = isClassDeclaration())
{
cd = cd.baseClass;
if (cd && !cd.determineSize(loc))
goto Lfail;
}

// Determine instance fields when sizeok == Sizeok.none
if (!this.determineFields())
goto Lfail;
if (sizeok != Sizeok.done)
finalizeSize();

// this aggregate type has:
if (type.ty == Terror)
return false; // marked as invalid during the finalizing.
if (sizeok == Sizeok.done)
return true; // succeeded to calculate instance size.

Lfail:
// There's unresolvable forward reference.
if (type != Type.terror)
error(loc, "%s `%s` no size because of forward reference", kind, toPrettyChars);
// Don't cache errors from speculative semantic, might be resolvable later.
// https://issues.dlang.org/show_bug.cgi?id=16574
if (!global.gag)
{
type = Type.terror;
errors = true;
}
return false;
}

abstract void finalizeSize();

override final uinteger_t size(const ref Loc loc)
{
//printf("+AggregateDeclaration::size() %s, scope = %p, sizeok = %d\n", toChars(), _scope, sizeok);
Expand Down
3 changes: 0 additions & 3 deletions compiler/src/dmd/aggregate.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ class AggregateDeclaration : public ScopeDsymbol
Sizeok sizeok; // set when structsize contains valid data

virtual Scope *newScope(Scope *sc);
virtual void finalizeSize() = 0;
uinteger_t size(const Loc &loc) override final;
bool fill(const Loc &loc, Expressions &elements, bool ctorinit);
Type *getType() override final;
Expand Down Expand Up @@ -171,7 +170,6 @@ class StructDeclaration : public AggregateDeclaration
static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s) override;
const char *kind() const override;
void finalizeSize() override final;
bool isPOD();
bool zeroInit() const; // !=0 if initialize with 0 fill
bool zeroInit(bool v);
Expand Down Expand Up @@ -288,7 +286,6 @@ class ClassDeclaration : public AggregateDeclaration
virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);

bool isBaseInfoComplete();
void finalizeSize() override;
bool hasMonitor();
bool isFuncHidden(FuncDeclaration *fd);
bool isCOMclass() const;
Expand Down
110 changes: 0 additions & 110 deletions compiler/src/dmd/dclass.d
Original file line number Diff line number Diff line change
Expand Up @@ -496,116 +496,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return null;
}

final override void finalizeSize()
{
assert(sizeok != Sizeok.done);

// Set the offsets of the fields and determine the size of the class
if (baseClass)
{
assert(baseClass.sizeok == Sizeok.done);

alignsize = baseClass.alignsize;
if (classKind == ClassKind.cpp)
structsize = target.cpp.derivedClassOffset(baseClass);
else
structsize = baseClass.structsize;
}
else if (classKind == ClassKind.objc)
structsize = 0; // no hidden member for an Objective-C class
else if (isInterfaceDeclaration())
{
if (interfaces.length == 0)
{
alignsize = target.ptrsize;
structsize = target.ptrsize; // allow room for __vptr
}
}
else
{
alignsize = target.ptrsize;
structsize = target.ptrsize; // allow room for __vptr
if (hasMonitor())
structsize += target.ptrsize; // allow room for __monitor
}

//printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
size_t bi = 0; // index into vtblInterfaces[]

/****
* Runs through the inheritance graph to set the BaseClass.offset fields.
* Recursive in order to account for the size of the interface classes, if they are
* more than just interfaces.
* Params:
* cd = interface to look at
* baseOffset = offset of where cd will be placed
* Returns:
* subset of instantiated size used by cd for interfaces
*/
uint membersPlace(ClassDeclaration cd, uint baseOffset)
{
//printf(" membersPlace(%s, %d)\n", cd.toChars(), baseOffset);
uint offset = baseOffset;

foreach (BaseClass* b; cd.interfaces)
{
if (b.sym.sizeok != Sizeok.done)
b.sym.finalizeSize();
assert(b.sym.sizeok == Sizeok.done);

if (!b.sym.alignsize)
b.sym.alignsize = target.ptrsize;
offset = alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, offset);
assert(bi < vtblInterfaces.length);

BaseClass* bv = (*vtblInterfaces)[bi];
if (b.sym.interfaces.length == 0)
{
//printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset);
bv.offset = offset;
++bi;
// All the base interfaces down the left side share the same offset
for (BaseClass* b2 = bv; b2.baseInterfaces.length; )
{
b2 = &b2.baseInterfaces[0];
b2.offset = offset;
//printf("\tvtblInterfaces[%d] b=%p sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset);
}
}
membersPlace(b.sym, offset);
//printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize);
offset += b.sym.structsize;
if (alignsize < b.sym.alignsize)
alignsize = b.sym.alignsize;
}
return offset - baseOffset;
}

structsize += membersPlace(this, structsize);

if (isInterfaceDeclaration())
{
sizeok = Sizeok.done;
return;
}

// FIXME: Currently setFieldOffset functions need to increase fields
// to calculate each variable offsets. It can be improved later.
fields.setDim(0);

FieldState fieldState;
fieldState.offset = structsize;
foreach (s; *members)
{
s.setFieldOffset(this, &fieldState, false);
}

sizeok = Sizeok.done;

// Calculate fields[i].overlapped
checkOverlappedFields();
}

/**************
* Returns: true if there's a __monitor field
*/
Expand Down
121 changes: 0 additions & 121 deletions compiler/src/dmd/dstruct.d
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import dmd.identifier;
import dmd.location;
import dmd.mtype;
import dmd.opover;
import dmd.target;
import dmd.tokens;
import dmd.typesem;
import dmd.typinf;
Expand Down Expand Up @@ -149,126 +148,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return "struct";
}

override final void finalizeSize()
{
//printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
assert(sizeok != Sizeok.done);

if (sizeok == Sizeok.inProcess)
{
return;
}
sizeok = Sizeok.inProcess;

//printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok);

fields.setDim(0); // workaround

// Set the offsets of the fields and determine the size of the struct
FieldState fieldState;
bool isunion = isUnionDeclaration() !is null;
for (size_t i = 0; i < members.length; i++)
{
Dsymbol s = (*members)[i];
s.setFieldOffset(this, &fieldState, isunion);
}
if (type.ty == Terror)
{
errors = true;
return;
}

if (structsize == 0)
{
hasNoFields = true;
alignsize = 1;

// A fine mess of what size a zero sized struct should be
final switch (classKind)
{
case ClassKind.d:
case ClassKind.cpp:
structsize = 1;
break;

case ClassKind.c:
case ClassKind.objc:
if (target.c.bitFieldStyle == TargetC.BitFieldStyle.MS)
{
/* Undocumented MS behavior for:
* struct S { int :0; };
*/
structsize = 4;
}
else
structsize = 0;
break;
}
}

// Round struct size up to next alignsize boundary.
// This will ensure that arrays of structs will get their internals
// aligned properly.
if (alignment.isDefault() || alignment.isPack())
structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
else
structsize = (structsize + alignment.get() - 1) & ~(alignment.get() - 1);

sizeok = Sizeok.done;

//printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), cast(int)fields.length, cast(int)structsize);

if (errors)
return;

// Calculate fields[i].overlapped
if (checkOverlappedFields())
{
errors = true;
return;
}

// Determine if struct is all zeros or not
zeroInit = true;
auto lastOffset = -1;
foreach (vd; fields)
{
// First skip zero sized fields
if (vd.type.size(vd.loc) == 0)
continue;

// only consider first sized member of an (anonymous) union
if (vd.overlapped && vd.offset == lastOffset)
continue;
lastOffset = vd.offset;

if (vd._init)
{
if (vd._init.isVoidInitializer())
/* Treat as 0 for the purposes of putting the initializer
* in the BSS segment, or doing a mass set to 0
*/
continue;

// Examine init to see if it is all 0s.
auto exp = vd.getConstInitializer();
if (!exp || !_isZeroInit(exp))
{
zeroInit = false;
break;
}
}
else if (!vd.type.isZeroInit(loc))
{
zeroInit = false;
break;
}
}


argTypes = target.toArgTypes(type);
}

/// Compute cached type properties for `TypeStruct`
extern(D) final void determineTypeProperties()
{
Expand Down
Loading

0 comments on commit dd0f71d

Please sign in to comment.