summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-check-decl.cpp238
1 files 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<ConstructorDecl*> _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<ConstructorDecl*> 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<DeclAndCtorInfo>& inheritanceDefaultCtorList, StructDecl* structDecl);
+ void synthesizeCtorBodyForBases(ConstructorDecl* ctor, List<DeclAndCtorInfo>& inheritanceDefaultCtorList, ThisExpr* thisExpr, SeqStmt* seqStmtChild);
+ void synthesizeCtorBodyForMember(ConstructorDecl* ctor, Decl* member, ThisExpr* thisExpr, Dictionary<Decl*, Expr*>& cachedDeclToCheckedVar, SeqStmt* seqStmtChild);
};
template<typename VisitorType>
@@ -8470,33 +8493,118 @@ namespace Slang
return as<SeqStmt>(stmt->body);
}
- void SemanticsDeclBodyVisitor::visitAggTypeDecl(AggTypeDecl* aggTypeDecl)
+ void SemanticsDeclBodyVisitor::synthesizeCtorBodyForBases(ConstructorDecl* ctor, List<DeclAndCtorInfo>& inheritanceDefaultCtorList, ThisExpr* thisExpr, SeqStmt* seqStmtChild)
{
- if (aggTypeDecl->hasTag(TypeTag::Incomplete) && aggTypeDecl->hasModifier<HLSLExportModifier>())
+ // 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<VarExpr>();
+ ctorToInvoke->declRef = declInfo.defaultCtor->getDefaultDeclRef();
+ ctorToInvoke->name = declInfo.defaultCtor->getName();
+ ctorToInvoke->loc = declInfo.defaultCtor->loc;
+ ctorToInvoke->type = m_astBuilder->getFuncType(ArrayView<Type*>(), ctor->returnType.type);
+
+ auto invoke = m_astBuilder->create<InvokeExpr>();
+ invoke->functionExpr = ctorToInvoke;
+
+ auto assign = m_astBuilder->create<AssignExpr>();
+ assign->left = coerce(CoercionSite::Initializer, declInfo.defaultCtor->returnType.type, thisExpr);
+ assign->right = invoke;
+ auto stmt = m_astBuilder->create<ExpressionStmt>();
+ stmt->expression = assign;
+ stmt->loc = ctor->loc;
+
+ seqStmtChild->stmts.add(stmt);
}
-
- auto structDecl = as<StructDecl>(aggTypeDecl);
- if (!structDecl)
+ }
+
+ void SemanticsDeclBodyVisitor::synthesizeCtorBodyForMember(ConstructorDecl* ctor, Decl* member, ThisExpr* thisExpr, Dictionary<Decl*, Expr*>& cachedDeclToCheckedVar, SeqStmt* seqStmtChild)
+ {
+ auto varDeclBase = as<VarDeclBase>(member);
+
+ // Static variables are initialized at start of runtime, not inside a constructor
+ if (!varDeclBase
+ || !varDeclBase->initExpr
+ || varDeclBase->hasModifier<HLSLStaticModifier>())
return;
- struct DeclAndCtorInfo
+ MemberExpr* memberExpr = m_astBuilder->create<MemberExpr>();
+ 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<AssignExpr>();
+ assign->left = memberExpr;
+ assign->right = varDeclBase->initExpr;
+ assign->loc = member->loc;
+
+ auto stmt = m_astBuilder->create<ExpressionStmt>();
+ stmt->expression = assign;
+ stmt->loc = member->loc;
+
+ Expr* checkedMemberVarExpr;
+ if (cachedDeclToCheckedVar.containsKey(member))
+ checkedMemberVarExpr = cachedDeclToCheckedVar[member];
+ else
{
- StructDecl* parent = nullptr;
- ConstructorDecl* defaultCtor = nullptr;
- List<ConstructorDecl*> ctorList;
- DeclAndCtorInfo()
+ checkedMemberVarExpr = CheckTerm(memberExpr);
+ cachedDeclToCheckedVar.add({ member, checkedMemberVarExpr });
+ }
+
+ if (!checkedMemberVarExpr->type.isLeftValue)
+ return;
+
+ seqStmtChild->stmts.add(stmt);
+ }
+
+
+ void SemanticsDeclBodyVisitor::synthesizeCtorBody(DeclAndCtorInfo& structDeclInfo, List<DeclAndCtorInfo>& inheritanceDefaultCtorList, StructDecl* structDecl)
+ {
+ Dictionary<Decl*, Expr*> cachedDeclToCheckedVar;
+ for (auto ctor : structDeclInfo.ctorList)
+ {
+ auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor);
+ auto seqStmtChild = m_astBuilder->create<SeqStmt>();
+ seqStmtChild->stmts.reserve(inheritanceDefaultCtorList.getCount() + structDecl->members.getCount());
+
+ ThisExpr* thisExpr = m_astBuilder->create<ThisExpr>();
+ 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<HLSLExportModifier>())
+ {
+ getSink()->diagnose(aggTypeDecl->loc, Diagnostics::cannotExportIncompleteType, aggTypeDecl);
+ }
+
+ auto structDecl = as<StructDecl>(aggTypeDecl);
+ if (!structDecl)
+ return;
+
List<DeclAndCtorInfo> inheritanceDefaultCtorList{};
for (auto inheritanceMember : structDecl->getMembersOfType<InheritanceDecl>())
{
@@ -8525,101 +8633,7 @@ namespace Slang
varDeclBase->initExpr = constructDefaultInitExprForVar(this, varDeclBase);
}
- Index insertOffset = 0;
- Dictionary<Decl*, Expr*> cachedDeclToCheckedVar;
- for (auto ctor : structDeclInfo.ctorList)
- {
- auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor);
- auto seqStmtChild = m_astBuilder->create<SeqStmt>();
- seqStmtChild->stmts.reserve(inheritanceDefaultCtorList.getCount());
- for (auto& declInfo : inheritanceDefaultCtorList)
- {
- if (!declInfo.defaultCtor)
- continue;
-
- auto ctorToInvoke = m_astBuilder->create<VarExpr>();
- ctorToInvoke->declRef = declInfo.defaultCtor->getDefaultDeclRef();
- ctorToInvoke->name = declInfo.defaultCtor->getName();
- ctorToInvoke->loc = declInfo.defaultCtor->loc;
- ctorToInvoke->type = m_astBuilder->getFuncType(ArrayView<Type*>(), structDeclInfo.defaultCtor->returnType.type);
-
- auto invoke = m_astBuilder->create<InvokeExpr>();
- invoke->functionExpr = ctorToInvoke;
-
- ThisExpr* thisExpr = m_astBuilder->create<ThisExpr>();
- thisExpr->scope = ctor->ownedScope;
- thisExpr->type = ctor->returnType.type;
-
- auto assign = m_astBuilder->create<AssignExpr>();
- assign->left = coerce(CoercionSite::Initializer, declInfo.defaultCtor->returnType.type, thisExpr);
- assign->right = invoke;
- auto stmt = m_astBuilder->create<ExpressionStmt>();
- 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>();
- thisExpr->scope = ctor->ownedScope;
- thisExpr->type = ctor->returnType.type;
-
- auto seqStmt = _ensureCtorBodyIsSeqStmt(m_astBuilder, ctor);
- auto seqStmtChild = m_astBuilder->create<SeqStmt>();
- seqStmtChild->stmts.reserve(structDecl->members.getCount());
- for (auto& m : structDecl->members)
- {
- auto varDeclBase = as<VarDeclBase>(m);
-
- // Static variables are initialized at start of runtime, not inside a constructor
- if (!varDeclBase
- || !varDeclBase->initExpr
- || varDeclBase->hasModifier<HLSLStaticModifier>())
- continue;
-
- MemberExpr* memberExpr = m_astBuilder->create<MemberExpr>();
- 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<AssignExpr>();
- assign->left = memberExpr;
- assign->right = varDeclBase->initExpr;
- assign->loc = m->loc;
-
- auto stmt = m_astBuilder->create<ExpressionStmt>();
- 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)
{