From ff51c21ba217fe18bf22fec7bf822cde779b265d Mon Sep 17 00:00:00 2001 From: kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:22:32 -0500 Subject: Refactor the code for synthesizing the body of constructor (#5231) --- source/slang/slang-check-decl.cpp | 238 ++++++++++++++++++++------------------ 1 file changed, 126 insertions(+), 112 deletions(-) diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 8c3429c9a..b7f65a11a 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -21,6 +21,9 @@ namespace Slang { + static ConstructorDecl* _getDefaultCtor(StructDecl* structDecl); + static List _getCtorList(ASTBuilder* m_astBuilder, SemanticsVisitor* visitor, StructDecl* structDecl, ConstructorDecl** defaultCtorOut); + /// Visitor to transition declarations to `DeclCheckState::CheckedModifiers` struct SemanticsDeclModifiersVisitor : public SemanticsDeclVisitorBase @@ -316,6 +319,26 @@ namespace Slang SemanticsContext registerDifferentiableTypesForFunc(FunctionDeclBase* funcDecl); + struct DeclAndCtorInfo + { + StructDecl* parent = nullptr; + ConstructorDecl* defaultCtor = nullptr; + List ctorList; + DeclAndCtorInfo() + { + } + DeclAndCtorInfo(ASTBuilder* m_astBuilder, SemanticsVisitor* visitor, StructDecl* parent, const bool getOnlyDefault) + { + if (getOnlyDefault) + defaultCtor = _getDefaultCtor(parent); + else + ctorList = _getCtorList(m_astBuilder, visitor, parent, &defaultCtor); + } + }; + + void synthesizeCtorBody(DeclAndCtorInfo& structDeclInfo, List& inheritanceDefaultCtorList, StructDecl* structDecl); + void synthesizeCtorBodyForBases(ConstructorDecl* ctor, List& inheritanceDefaultCtorList, ThisExpr* thisExpr, SeqStmt* seqStmtChild); + void synthesizeCtorBodyForMember(ConstructorDecl* ctor, Decl* member, ThisExpr* thisExpr, Dictionary& cachedDeclToCheckedVar, SeqStmt* seqStmtChild); }; template @@ -8470,33 +8493,118 @@ namespace Slang return as(stmt->body); } - void SemanticsDeclBodyVisitor::visitAggTypeDecl(AggTypeDecl* aggTypeDecl) + void SemanticsDeclBodyVisitor::synthesizeCtorBodyForBases(ConstructorDecl* ctor, List& inheritanceDefaultCtorList, ThisExpr* thisExpr, SeqStmt* seqStmtChild) { - if (aggTypeDecl->hasTag(TypeTag::Incomplete) && aggTypeDecl->hasModifier()) + // e.g. this->base = BaseType(); + for (auto& declInfo : inheritanceDefaultCtorList) { - getSink()->diagnose(aggTypeDecl->loc, Diagnostics::cannotExportIncompleteType, aggTypeDecl); + if (!declInfo.defaultCtor) + continue; + + auto ctorToInvoke = m_astBuilder->create(); + ctorToInvoke->declRef = declInfo.defaultCtor->getDefaultDeclRef(); + ctorToInvoke->name = declInfo.defaultCtor->getName(); + ctorToInvoke->loc = declInfo.defaultCtor->loc; + ctorToInvoke->type = m_astBuilder->getFuncType(ArrayView(), ctor->returnType.type); + + auto invoke = m_astBuilder->create(); + invoke->functionExpr = ctorToInvoke; + + auto assign = m_astBuilder->create(); + assign->left = coerce(CoercionSite::Initializer, declInfo.defaultCtor->returnType.type, thisExpr); + assign->right = invoke; + auto stmt = m_astBuilder->create(); + stmt->expression = assign; + stmt->loc = ctor->loc; + + seqStmtChild->stmts.add(stmt); } - - auto structDecl = as(aggTypeDecl); - if (!structDecl) + } + + void SemanticsDeclBodyVisitor::synthesizeCtorBodyForMember(ConstructorDecl* ctor, Decl* member, ThisExpr* thisExpr, Dictionary& cachedDeclToCheckedVar, SeqStmt* seqStmtChild) + { + auto varDeclBase = as(member); + + // Static variables are initialized at start of runtime, not inside a constructor + if (!varDeclBase + || !varDeclBase->initExpr + || varDeclBase->hasModifier()) return; - struct DeclAndCtorInfo + MemberExpr* memberExpr = m_astBuilder->create(); + memberExpr->baseExpression = thisExpr; + memberExpr->declRef = member->getDefaultDeclRef(); + memberExpr->scope = ctor->ownedScope; + memberExpr->loc = member->loc; + memberExpr->name = member->getName(); + memberExpr->type = DeclRefType::create(getASTBuilder(), member->getDefaultDeclRef()); + + auto assign = m_astBuilder->create(); + assign->left = memberExpr; + assign->right = varDeclBase->initExpr; + assign->loc = member->loc; + + auto stmt = m_astBuilder->create(); + stmt->expression = assign; + stmt->loc = member->loc; + + Expr* checkedMemberVarExpr; + if (cachedDeclToCheckedVar.containsKey(member)) + checkedMemberVarExpr = cachedDeclToCheckedVar[member]; + else { - StructDecl* parent = nullptr; - ConstructorDecl* defaultCtor = nullptr; - List ctorList; - DeclAndCtorInfo() + checkedMemberVarExpr = CheckTerm(memberExpr); + cachedDeclToCheckedVar.add({ member, checkedMemberVarExpr }); + } + + if (!checkedMemberVarExpr->type.isLeftValue) + return; + + seqStmtChild->stmts.add(stmt); + } + + + void SemanticsDeclBodyVisitor::synthesizeCtorBody(DeclAndCtorInfo& structDeclInfo, List& inheritanceDefaultCtorList, StructDecl* structDecl) + { + Dictionary cachedDeclToCheckedVar; + for (auto ctor : structDeclInfo.ctorList) + { + auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor); + auto seqStmtChild = m_astBuilder->create(); + seqStmtChild->stmts.reserve(inheritanceDefaultCtorList.getCount() + structDecl->members.getCount()); + + ThisExpr* thisExpr = m_astBuilder->create(); + thisExpr->scope = ctor->ownedScope; + thisExpr->type = ctor->returnType.type; + + // Initialize base type by using its default constructor if it has one. + synthesizeCtorBodyForBases(ctor, inheritanceDefaultCtorList, thisExpr, seqStmtChild); + + // Initialize member variables by using their default value if they have one + // e.g. this->member = default_value + for (auto& m : structDecl->members) { + synthesizeCtorBodyForMember(ctor, m, thisExpr, cachedDeclToCheckedVar, seqStmtChild); } - DeclAndCtorInfo(ASTBuilder* m_astBuilder, SemanticsVisitor* visitor, StructDecl* parent, const bool getOnlyDefault) + + if (seqStmtChild->stmts.getCount() != 0) { - if (getOnlyDefault) - defaultCtor = _getDefaultCtor(parent); - else - ctorList = _getCtorList(m_astBuilder, visitor, parent, &defaultCtor); + seqStmt->stmts.insert(0, seqStmtChild); } - }; + } + } + + void SemanticsDeclBodyVisitor::visitAggTypeDecl(AggTypeDecl* aggTypeDecl) + { + if (aggTypeDecl->hasTag(TypeTag::Incomplete) && aggTypeDecl->hasModifier()) + { + getSink()->diagnose(aggTypeDecl->loc, Diagnostics::cannotExportIncompleteType, aggTypeDecl); + } + + auto structDecl = as(aggTypeDecl); + if (!structDecl) + return; + List inheritanceDefaultCtorList{}; for (auto inheritanceMember : structDecl->getMembersOfType()) { @@ -8525,101 +8633,7 @@ namespace Slang varDeclBase->initExpr = constructDefaultInitExprForVar(this, varDeclBase); } - Index insertOffset = 0; - Dictionary cachedDeclToCheckedVar; - for (auto ctor : structDeclInfo.ctorList) - { - auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor); - auto seqStmtChild = m_astBuilder->create(); - seqStmtChild->stmts.reserve(inheritanceDefaultCtorList.getCount()); - for (auto& declInfo : inheritanceDefaultCtorList) - { - if (!declInfo.defaultCtor) - continue; - - auto ctorToInvoke = m_astBuilder->create(); - ctorToInvoke->declRef = declInfo.defaultCtor->getDefaultDeclRef(); - ctorToInvoke->name = declInfo.defaultCtor->getName(); - ctorToInvoke->loc = declInfo.defaultCtor->loc; - ctorToInvoke->type = m_astBuilder->getFuncType(ArrayView(), structDeclInfo.defaultCtor->returnType.type); - - auto invoke = m_astBuilder->create(); - invoke->functionExpr = ctorToInvoke; - - ThisExpr* thisExpr = m_astBuilder->create(); - thisExpr->scope = ctor->ownedScope; - thisExpr->type = ctor->returnType.type; - - auto assign = m_astBuilder->create(); - assign->left = coerce(CoercionSite::Initializer, declInfo.defaultCtor->returnType.type, thisExpr); - assign->right = invoke; - auto stmt = m_astBuilder->create(); - stmt->expression = assign; - stmt->loc = ctor->loc; - - seqStmtChild->stmts.add(stmt); - } - - if (seqStmtChild->stmts.getCount() == 0) - continue; - - seqStmt->stmts.insert(0, seqStmtChild); - insertOffset = 1; - } - - for (auto ctor : structDeclInfo.ctorList) - { - ThisExpr* thisExpr = m_astBuilder->create(); - thisExpr->scope = ctor->ownedScope; - thisExpr->type = ctor->returnType.type; - - auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor); - auto seqStmtChild = m_astBuilder->create(); - seqStmtChild->stmts.reserve(structDecl->members.getCount()); - for (auto& m : structDecl->members) - { - auto varDeclBase = as(m); - - // Static variables are initialized at start of runtime, not inside a constructor - if (!varDeclBase - || !varDeclBase->initExpr - || varDeclBase->hasModifier()) - continue; - - MemberExpr* memberExpr = m_astBuilder->create(); - memberExpr->baseExpression = thisExpr; - memberExpr->declRef = m->getDefaultDeclRef(); - memberExpr->scope = ctor->ownedScope; - memberExpr->loc = m->loc; - memberExpr->name = m->getName(); - memberExpr->type = DeclRefType::create(getASTBuilder(), m->getDefaultDeclRef()); - - auto assign = m_astBuilder->create(); - assign->left = memberExpr; - assign->right = varDeclBase->initExpr; - assign->loc = m->loc; - - auto stmt = m_astBuilder->create(); - stmt->expression = assign; - stmt->loc = m->loc; - - Expr* checkedMemberVarExpr; - if (cachedDeclToCheckedVar.containsKey(m)) - checkedMemberVarExpr = cachedDeclToCheckedVar[m]; - else - { - checkedMemberVarExpr = CheckTerm(memberExpr); - cachedDeclToCheckedVar.add({ m, checkedMemberVarExpr }); - } - if (!checkedMemberVarExpr->type.isLeftValue) - continue; - - seqStmtChild->stmts.add(stmt); - } - if (seqStmtChild->stmts.getCount() == 0) - continue; - seqStmt->stmts.insert(insertOffset, seqStmtChild); - } + synthesizeCtorBody(structDeclInfo, inheritanceDefaultCtorList, structDecl); if (structDeclInfo.defaultCtor) { -- cgit v1.2.3