Skip to content

Commit

Permalink
Handle new extern(C) structs with size 0
Browse files Browse the repository at this point in the history
The linkage now (2.098) also affects the size of empty structs - e.g.,
1 for extern(C++), 0 for Posix extern(C), 4 for MSVC extern(C).

This also affects beauties like `extern(C) struct S { double[0] a; }`,
as tested by dmd-testsuite's runnable/ldc_cabi1.d, which is hereby
fixed for Posix - don't try to GEP into an empty LL struct.
  • Loading branch information
kinke committed Sep 8, 2021
1 parent 1537198 commit 3f11044
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 14 deletions.
29 changes: 17 additions & 12 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1844,27 +1844,32 @@ LLValue *DtoIndexAggregate(LLValue *src, AggregateDeclaration *ad,
// ourselves, DtoType below would be enough.
DtoResolveDsymbol(ad);

// Cast the pointer we got to the canonical struct type the indices are
// based on.
LLType *st = DtoType(ad->type);
if (ad->isStructDeclaration()) {
st = getPtrToType(st);
}
src = DtoBitCast(src, st);

// Look up field to index and any offset to apply.
// Look up field to index or offset to apply.
unsigned fieldIndex;
unsigned byteOffset;
auto irTypeAggr = getIrType(ad->type)->isAggr();
assert(irTypeAggr);
irTypeAggr->getMemberLocation(vd, fieldIndex, byteOffset);

LLValue *val = DtoGEP(src, 0, fieldIndex);

LLValue *val = src;
if (byteOffset) {
// Cast to void* to apply byte-wise offset.
assert(fieldIndex == 0);
// Cast to void* to apply byte-wise offset from object start.
val = DtoBitCast(val, getVoidPtrType());
val = DtoGEP1(val, byteOffset);
} else {
if (ad->structsize == 0) { // can happen for extern(C) structs
assert(fieldIndex == 0);
} else {
// Cast the pointer we got to the canonical struct type the indices are
// based on.
LLType *st = DtoType(ad->type);
if (ad->isStructDeclaration()) {
st = getPtrToType(st);
}
val = DtoBitCast(val, st);
val = DtoGEP(val, 0, fieldIndex);
}
}

// Cast the (possibly void*) pointer to the canonical variable type.
Expand Down
2 changes: 0 additions & 2 deletions ir/iraggr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,6 @@ IrAggr::createInitializerConstant(const VarInitMap &explicitInitializers) {
if (offset < structsize)
add_zeros(constants, offset, structsize);

assert(!constants.empty());

// get LL field types
llvm::SmallVector<llvm::Type *, 16> types;
types.reserve(constants.size());
Expand Down

0 comments on commit 3f11044

Please sign in to comment.