From 34c353dbab61a6f7b14cfa76a18b1c71eb6c4690 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 18 Aug 2024 17:53:56 +0200 Subject: [PATCH] Lazily define class *memory* IR type To break remaining cycles in DtoType() - a class *ref* is an opaque IR pointer nowadays. --- ir/irtypeaggr.cpp | 3 ++- ir/irtypeaggr.h | 4 +++- ir/irtypeclass.cpp | 41 +++++++++++++++++++++++++++++------------ ir/irtypeclass.h | 4 +++- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/ir/irtypeaggr.cpp b/ir/irtypeaggr.cpp index c4f4c690096..a8ab7387697 100644 --- a/ir/irtypeaggr.cpp +++ b/ir/irtypeaggr.cpp @@ -279,10 +279,11 @@ IrTypeAggr::IrTypeAggr(AggregateDeclaration *ad) LLStructType::create(gIR->context(), ad->toPrettyChars())), aggr(ad) {} -unsigned IrTypeAggr::getMemberLocation(VarDeclaration *var, bool& isFieldIdx) const { +unsigned IrTypeAggr::getMemberLocation(VarDeclaration *var, bool& isFieldIdx) { // Note: The interface is a bit more general than what we actually return. // Specifically, the frontend offset information we use for overlapping // fields is always based at the object start. + const auto &varGEPIndices = getVarGEPIndices(); auto it = varGEPIndices.find(var); if (it != varGEPIndices.end()) { isFieldIdx = true; diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h index 780aab80000..1907cb37214 100644 --- a/ir/irtypeaggr.h +++ b/ir/irtypeaggr.h @@ -72,7 +72,7 @@ class IrTypeAggr : public IrType { /// Returns the index of the field in the LLVM struct type that corresponds /// to the given member variable, plus the offset to the actual field start /// due to overlapping (union) fields, if any. - unsigned getMemberLocation(VarDeclaration *var, bool& isFieldIdx) const; + unsigned getMemberLocation(VarDeclaration *var, bool& isFieldIdx); protected: /// @@ -90,6 +90,8 @@ class IrTypeAggr : public IrType { /// the field index of a variable in the frontend, it only stores the byte /// offset. VarGEPIndices varGEPIndices; + + virtual const VarGEPIndices &getVarGEPIndices() { return varGEPIndices; } }; // A helper for aggregating consecutive bit fields to a group. diff --git a/ir/irtypeclass.cpp b/ir/irtypeclass.cpp index ad35dacdbc5..3e540d425ee 100644 --- a/ir/irtypeclass.cpp +++ b/ir/irtypeclass.cpp @@ -68,17 +68,26 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) { const auto t = new IrTypeClass(cd); getIrType(cd->type) = t; + return t; +} + +llvm::Type *IrTypeClass::getLLType() { return getOpaquePtrType(); } + +llvm::Type *IrTypeClass::getMemoryLLType() { + if (!isaStruct(type)->isOpaque()) + return type; + const unsigned instanceSize = cd->structsize; IF_LOG Logger::println("Instance size: %u", instanceSize); AggrTypeBuilder builder; // add vtbl - builder.addType(llvm::PointerType::get(t->vtbl_type, 0), target.ptrsize); + builder.addType(llvm::PointerType::get(vtbl_type, 0), target.ptrsize); if (cd->isInterfaceDeclaration()) { // interfaces are just a vtable - t->num_interface_vtbls = + num_interface_vtbls = cd->vtblInterfaces ? cd->vtblInterfaces->length : 0; } else { // classes have monitor and fields @@ -88,7 +97,7 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) { } // add data members recursively - t->addClassData(builder, cd); + addClassData(builder, cd); // add tail padding if (instanceSize) // can be 0 for opaque classes @@ -96,25 +105,23 @@ IrTypeClass *IrTypeClass::get(ClassDeclaration *cd) { } // set struct body and copy GEP indices - isaStruct(t->type)->setBody(builder.defaultTypes(), builder.isPacked()); - t->varGEPIndices = builder.varGEPIndices(); + isaStruct(type)->setBody(builder.defaultTypes(), builder.isPacked()); + varGEPIndices = builder.varGEPIndices(); if (!cd->isInterfaceDeclaration() && instanceSize && - getTypeAllocSize(t->type) != instanceSize) { + getTypeAllocSize(type) != instanceSize) { error(cd->loc, "ICE: class IR size does not match the frontend size"); fatal(); } - IF_LOG Logger::cout() << "class type: " << *t->type << std::endl; + IF_LOG Logger::cout() << "class type: " << *type << std::endl; - return t; + return type; } -llvm::Type *IrTypeClass::getLLType() { return llvm::PointerType::get(type, 0); } - -llvm::Type *IrTypeClass::getMemoryLLType() { return type; } - size_t IrTypeClass::getInterfaceIndex(ClassDeclaration *inter) { + getMemoryLLType(); // lazily resolve + auto it = interfaceMap.find(inter); if (it == interfaceMap.end()) { return ~0UL; @@ -122,6 +129,16 @@ size_t IrTypeClass::getInterfaceIndex(ClassDeclaration *inter) { return it->second; } +unsigned IrTypeClass::getNumInterfaceVtbls() { + getMemoryLLType(); // lazily resolve + return num_interface_vtbls; +} + +const VarGEPIndices &IrTypeClass::getVarGEPIndices() { + getMemoryLLType(); // lazily resolve + return varGEPIndices; +} + void IrTypeClass::addInterfaceToMap(ClassDeclaration *inter, size_t index) { // don't duplicate work or overwrite indices if (interfaceMap.find(inter) != interfaceMap.end()) { diff --git a/ir/irtypeclass.h b/ir/irtypeclass.h index 95c9e22217c..7ad19859d92 100644 --- a/ir/irtypeclass.h +++ b/ir/irtypeclass.h @@ -47,7 +47,7 @@ class IrTypeClass : public IrTypeAggr { /// Returns the number of interface implementations (vtables) in this /// class. - unsigned getNumInterfaceVtbls() { return num_interface_vtbls; } + unsigned getNumInterfaceVtbls(); protected: /// @@ -73,6 +73,8 @@ class IrTypeClass : public IrTypeAggr { ////////////////////////////////////////////////////////////////////////// + const VarGEPIndices &getVarGEPIndices() override; + /// Adds the data members for the given class to the type builder, including /// those inherited from base classes/interfaces. void addClassData(AggrTypeBuilder &builder, ClassDeclaration *currCd);