diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2025-05-22 21:29:06 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-22 19:29:06 -0700 |
| commit | 3072cfea95aad2a9ddab0f517c8f18f634442a27 (patch) | |
| tree | 966c019c35604b0f457caec02c9619feddbf2665 /source | |
| parent | 2d34409f2e72673ac9fd766eaeaa75f60882e7ca (diff) | |
Implement default initializer list for C-Style type member (#7079)
* Implement default initializer list for C-Style type member
Close #6189.
Previsouly, for the C-Style member in a struct, if it doesn't have any initialize
expression, when we synthesize the ctor, we will not associate the
default value for the parameter corresponding to that member.
This bring some trouble that existing slang users has to add '= {}' to
every struct fields in order to make all the parameters in the synthesized ctor having
a default value, so people can still use `Struct a = {}` to create a
struct.
To make this use case convenience, we will automatically associated a
'= {}' as the default value for this case.
This PR also add support for empty initializing link-time sized vector/matrix by "= {}".
In addition, this PR also fix a bug in auto diff where we should not report error when proccessing
transpose on an empty struct.
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-check-conversion.cpp | 42 | ||||
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 25 | ||||
| -rw-r--r-- | source/slang/slang-ir-autodiff-transpose.h | 3 |
3 files changed, 66 insertions, 4 deletions
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp index 8f2ea3ca7..705da89e3 100644 --- a/source/slang/slang-check-conversion.cpp +++ b/source/slang/slang-check-conversion.cpp @@ -97,7 +97,17 @@ bool SemanticsVisitor::shouldUseInitializerDirectly(Type* toType, Expr* fromExpr // we want to check for is whether a direct initialization // is possible (a type conversion exists). // - return canCoerce(toType, fromExpr->type, fromExpr); + ConversionCost cost; + if (canCoerce(toType, fromExpr->type, fromExpr, &cost)) + { + if (cost >= kConversionCost_Explicit) + { + return false; + } + return true; + } + + return false; } bool SemanticsVisitor::_readValueFromInitializerList( @@ -526,6 +536,19 @@ bool SemanticsVisitor::_readAggregateValueFromInitializerList( } else { + auto isLinkTimeVal = + as<TypeCastIntVal>(toElementCount) || as<DeclRefIntVal>(toElementCount) || + as<PolynomialIntVal>(toElementCount) || as<FuncCallIntVal>(toElementType); + if (isLinkTimeVal) + { + auto defaultConstructExpr = m_astBuilder->create<DefaultConstructExpr>(); + defaultConstructExpr->loc = fromInitializerListExpr->loc; + defaultConstructExpr->type = QualType(toType); + + *outToExpr = defaultConstructExpr; + return true; + } + // We don't know the element count statically, // so what are we supposed to be doing? // @@ -702,12 +725,26 @@ bool SemanticsVisitor::_readAggregateValueFromInitializerList( auto toRowType = createVectorType(toMatrixType->getElementType(), toMatrixType->getColumnCount()); - if (auto constRowCount = as<ConstantIntVal>(toMatrixType->getRowCount())) + auto rowCountIntVal = toMatrixType->getRowCount(); + if (auto constRowCount = as<ConstantIntVal>(rowCountIntVal)) { rowCount = (UInt)constRowCount->getValue(); } else { + auto isLinkTimeVal = + as<TypeCastIntVal>(rowCountIntVal) || as<DeclRefIntVal>(rowCountIntVal) || + as<PolynomialIntVal>(rowCountIntVal) || as<FuncCallIntVal>(rowCountIntVal); + if (isLinkTimeVal) + { + auto defaultConstructExpr = m_astBuilder->create<DefaultConstructExpr>(); + defaultConstructExpr->loc = fromInitializerListExpr->loc; + defaultConstructExpr->type = QualType(toType); + + *outToExpr = defaultConstructExpr; + return true; + } + // We don't know the element count statically, // so what are we supposed to be doing? // @@ -1545,7 +1582,6 @@ bool SemanticsVisitor::_coerce( return true; } - // The main general-purpose approach for conversion is // using suitable marked initializer ("constructor") // declarations on the target type. diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index c03d8e985..1331839a4 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -2512,6 +2512,23 @@ static Expr* constructDefaultConstructorForType(SemanticsVisitor* visitor, Type* return invoke; } + // At the last, we will check if the type is a C-style type, if it is, we will use empty + // initializer list to construct the default constructor. + HashSet<Type*> visitSet; + if (visitor->isCStyleType(type, visitSet)) + { + auto initListExpr = visitor->getASTBuilder()->create<InitializerListExpr>(); + initListExpr->type = visitor->getASTBuilder()->getInitializerListType(); + Expr* outExpr = nullptr; + auto fromType = type; + if (auto atomicType = as<AtomicType>(fromType)) + { + fromType = atomicType->getElementType(); + } + if (visitor->_coerceInitializerList(fromType, &outExpr, initListExpr)) + return outExpr; + } + return nullptr; } @@ -13031,7 +13048,13 @@ static Expr* _getParamDefaultValue(SemanticsVisitor* visitor, VarDeclBase* varDe if (!isDefaultInitializable(varDecl)) return nullptr; - return constructDefaultConstructorForType(visitor, varDecl->type.type); + if (auto expr = constructDefaultConstructorForType(visitor, varDecl->type.type)) + { + expr->loc = varDecl->loc; + return expr; + } + + return nullptr; } bool SemanticsDeclAttributesVisitor::_synthesizeCtorSignature(StructDecl* structDecl) diff --git a/source/slang/slang-ir-autodiff-transpose.h b/source/slang/slang-ir-autodiff-transpose.h index 282cc9685..606428efe 100644 --- a/source/slang/slang-ir-autodiff-transpose.h +++ b/source/slang/slang-ir-autodiff-transpose.h @@ -1987,6 +1987,9 @@ struct DiffTransposePass IRInst* fwdMakeStruct, IRInst* revValue) { + if (fwdMakeStruct->getOperandCount() == 0) + return TranspositionResult(); + List<RevGradient> gradients; auto structType = cast<IRStructType>(fwdMakeStruct->getFullType()); UInt ii = 0; |
