summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2025-05-22 21:29:06 -0500
committerGitHub <noreply@github.com>2025-05-22 19:29:06 -0700
commit3072cfea95aad2a9ddab0f517c8f18f634442a27 (patch)
tree966c019c35604b0f457caec02c9619feddbf2665 /source
parent2d34409f2e72673ac9fd766eaeaa75f60882e7ca (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.cpp42
-rw-r--r--source/slang/slang-check-decl.cpp25
-rw-r--r--source/slang/slang-ir-autodiff-transpose.h3
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;