Add __traits(initSymbol, <aggregate type>) (#3774)

A clean way of directly accessing struct and class init symbols. It
yields a `const(void[])` slice; the length reflecting the struct/class
instance size, and the pointer either pointing to the init symbol or
being null for zero-initialized structs.

Paves the way for resolving #3773 in druntime as well as accessing class
init symbols without `TypeInfo_Class.initializer()` indirection, and so
with -betterC as well.
This commit is contained in:
Martin Kinkelin 2021-06-28 18:40:28 +02:00 committed by GitHub
parent 383129c3b0
commit c6096a7d27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 24 deletions

View file

@ -1573,23 +1573,32 @@ DValue *DtoSymbolAddress(const Loc &loc, Type *type, Declaration *decl) {
}
if (SymbolDeclaration *sdecl = decl->isSymbolDeclaration()) {
// this seems to be the static initialiser for structs
Type *sdecltype = sdecl->type->toBasetype();
IF_LOG Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct);
TypeStruct *ts = static_cast<TypeStruct *>(sdecltype);
StructDeclaration *sd = ts->sym;
assert(sd);
DtoResolveStruct(sd);
// this is the static initialiser (init symbol) for aggregates
AggregateDeclaration *ad = sdecl->dsym;
IF_LOG Logger::print("Sym: ad=%s\n", ad->toChars());
DtoResolveDsymbol(ad);
auto sd = ad->isStructDeclaration();
// LDC extension: void[]-typed `__traits(initSymbol)`, for classes too
auto tb = sdecl->type->toBasetype();
if (tb->ty != Tstruct) {
assert(tb->ty == Tarray && tb->nextOf()->ty == Tvoid);
const auto size = DtoConstSize_t(ad->structsize);
llvm::Constant *ptr =
sd && sd->zeroInit
? getNullValue(getVoidPtrType())
: DtoBitCast(getIrAggr(ad)->getInitSymbol(), getVoidPtrType());
return new DSliceValue(type, size, ptr);
}
assert(sd);
if (sd->zeroInit) {
error(loc, "no init symbol for zero-initialized struct");
fatal();
}
LLValue *initsym = getIrAggr(sd)->getInitSymbol();
initsym = DtoBitCast(initsym, DtoType(ts->pointerTo()));
return new DLValue(type, initsym);
return new DLValue(type, DtoBitCast(initsym, DtoPtrToType(sd->type)));
}
llvm_unreachable("Unimplemented VarExp type");