diff options
| -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 | ||||
| -rw-r--r-- | tests/diagnostics/extension-full-name.slang.expected | 25 | ||||
| -rw-r--r-- | tests/diagnostics/mismatching-types.slang.expected | 1 | ||||
| -rw-r--r-- | tests/initializer-list/c-style-type.slang | 2 | ||||
| -rw-r--r-- | tests/initializer-list/default-init-c-style-member.slang | 62 | ||||
| -rw-r--r-- | tests/initializer-list/generic-array-init.slang | 26 | ||||
| -rw-r--r-- | tests/initializer-list/partial-init.slang | 18 | ||||
| -rw-r--r-- | tests/initializer-list/struct-visibility-diagnostic-1.slang | 8 | ||||
| -rw-r--r-- | tests/initializer-list/struct-visibility-diagnostic-2.slang | 8 | ||||
| -rw-r--r-- | tests/initializer-list/struct-visibility-diagnostic-3.slang | 12 |
12 files changed, 191 insertions, 41 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; diff --git a/tests/diagnostics/extension-full-name.slang.expected b/tests/diagnostics/extension-full-name.slang.expected index 8001298c1..72eef77e3 100644 --- a/tests/diagnostics/extension-full-name.slang.expected +++ b/tests/diagnostics/extension-full-name.slang.expected @@ -1,39 +1,40 @@ result code = -1 standard error = { -tests/diagnostics/extension-full-name.slang(184): error 30019: expected an expression of type 'GenericType<half>.State', got 'int' +tests/diagnostics/extension-full-name.slang(185): error 30019: expected an expression of type 'GenericType<half>.State', got 'int' state1 = 0; // Error: expected expr of type 'GenericType<half>.State', got 'int' ^ -tests/diagnostics/extension-full-name.slang(185): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'int' +tests/diagnostics/extension-full-name.slang(186): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'int' options1 = 0; // Error: expected expr of type 'GenericType<float>.InnerType.Options', got 'int' ^ -tests/diagnostics/extension-full-name.slang(186): error 30019: expected an expression of type 'NonGenericType.Config', got 'int' +tests/diagnostics/extension-full-name.slang(187): error 30019: expected an expression of type 'NonGenericType.Config', got 'int' config1 = 0; // Error: expected expr of type 'NonGenericType.Config', got 'int' ^ -tests/diagnostics/extension-full-name.slang(187): error 30019: expected an expression of type 'Container.Nested.Settings', got 'int' +tests/diagnostics/extension-full-name.slang(188): error 30019: expected an expression of type 'Container.Nested.Settings', got 'int' settings1 = 0; // Error: expected expr of type 'Container.Nested.Settings', got 'int' ^ -tests/diagnostics/extension-full-name.slang(188): error 30019: expected an expression of type 'Container.Nested.DeepNested.Record', got 'int' +tests/diagnostics/extension-full-name.slang(189): error 30019: expected an expression of type 'Container.Nested.DeepNested.Record', got 'int' record1 = 0; // Error: expected expr of type 'Container.Nested.DeepNested.Record', got 'int' ^ -tests/diagnostics/extension-full-name.slang(196): error 30027: 'getOptions' is not a member of 'GenericType<int>.InnerType'. +tests/diagnostics/extension-full-name.slang(189): note: explicit conversion from 'int' to 'Container.Nested.DeepNested.Record' is possible +tests/diagnostics/extension-full-name.slang(197): error 30027: 'getOptions' is not a member of 'GenericType<int>.InnerType'. intInner.getOptions(); // This won't compile as intInner doesn't have getOptions ^~~~~~~~~~ -tests/diagnostics/extension-full-name.slang(226): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'GenericType<half>.State' +tests/diagnostics/extension-full-name.slang(227): error 30019: expected an expression of type 'GenericType<float>.InnerType.Options', got 'GenericType<half>.State' .createState(); // Error: expected expr of type 'GenericType<float>.InnerType.Options', ^ -tests/diagnostics/extension-full-name.slang(228): error 30019: expected an expression of type 'GenericType<half>.State', got 'NonGenericType.Config' +tests/diagnostics/extension-full-name.slang(229): error 30019: expected an expression of type 'GenericType<half>.State', got 'NonGenericType.Config' state1 = nonGenType.createConfig(); // Error: expected expr of type 'GenericType<half>.State', ^ -tests/diagnostics/extension-full-name.slang(230): error 30019: expected an expression of type 'NonGenericType.Config', got 'Container.Nested.Settings' +tests/diagnostics/extension-full-name.slang(231): error 30019: expected an expression of type 'NonGenericType.Config', got 'Container.Nested.Settings' config1 = nested.createSettings(); // Error: expected expr of type 'NonGenericType.Config', got ^ -tests/diagnostics/extension-full-name.slang(304): error 30019: expected an expression of type 'Bar[3].DataStats', got 'int' +tests/diagnostics/extension-full-name.slang(305): error 30019: expected an expression of type 'Bar[3].DataStats', got 'int' barStats = 0; // Error: expected expr of type 'Bar[3].DataStats', got 'int' ^ -tests/diagnostics/extension-full-name.slang(312): error 30019: expected an expression of type 'Bar[2].DataStats', got 'Bar[3].DataStats' +tests/diagnostics/extension-full-name.slang(313): error 30019: expected an expression of type 'Bar[2].DataStats', got 'Bar[3].DataStats' bar2Stats = barArray.computeStats(); // Error: expected expr of type 'Bar[2].DataStats', got 'Bar[3].DataStats' ^ -tests/diagnostics/extension-full-name.slang(355): error 30019: expected an expression of type 'SimpleBase.NamedConfig', got 'int' +tests/diagnostics/extension-full-name.slang(356): error 30019: expected an expression of type 'SimpleBase.NamedConfig', got 'int' config = 0; // Error: expected expr of type 'SimpleBase.NamedConfig', got 'int' ^ } diff --git a/tests/diagnostics/mismatching-types.slang.expected b/tests/diagnostics/mismatching-types.slang.expected index a706e30e6..e247d16a8 100644 --- a/tests/diagnostics/mismatching-types.slang.expected +++ b/tests/diagnostics/mismatching-types.slang.expected @@ -20,6 +20,7 @@ tests/diagnostics/mismatching-types.slang(63): error 30019: expected an expressi tests/diagnostics/mismatching-types.slang(66): error 30019: expected an expression of type 'NonGenericOuter.GenericInner<int>', got 'int' c.i = 0; ^ +tests/diagnostics/mismatching-types.slang(66): note: explicit conversion from 'int' to 'NonGenericOuter.GenericInner<int>' is possible tests/diagnostics/mismatching-types.slang(68): error 30019: expected an expression of type 'NonGenericOuter.GenericInner<int>', got 'NonGenericOuter.GenericInner<float>' c.i = c.f; ^ diff --git a/tests/initializer-list/c-style-type.slang b/tests/initializer-list/c-style-type.slang index 500bf37bb..8afa1e282 100644 --- a/tests/initializer-list/c-style-type.slang +++ b/tests/initializer-list/c-style-type.slang @@ -6,7 +6,7 @@ struct CLike int x; int y; // compiler synthesizes: - // __init(int x, int y); + // __init(int x = {}, int y = {}); } //TEST_INPUT:ubuffer(data=[0 0 0 0 0 0], stride=4):out,name=outputBuffer diff --git a/tests/initializer-list/default-init-c-style-member.slang b/tests/initializer-list/default-init-c-style-member.slang new file mode 100644 index 000000000..41dba5bd0 --- /dev/null +++ b/tests/initializer-list/default-init-c-style-member.slang @@ -0,0 +1,62 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -vk +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj + +struct NonCStyle +{ + int x; + __init(int x) + { + this.x = x; + } +} + +struct CLike +{ + NonCStyle nonCStyleMember; + int x; + int y; + // compiler synthesizes: + // __init(NonCStyle nonCStyleMember, int x = {}, int y = {}); +} + +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<int> outputBuffer; +void test() +{ + // case 1: initialized with synthesized ctor call, but CLike::x and CLike::y are default initialized + // and `c1` is now `{1, 0, 0}`. + CLike c1 = {NonCStyle(1)}; + + // case 2: initialized with synthesized ctor call, CLike::y are default initialized + CLike c2 = {NonCStyle(1), 2}; + + // case 3: initialized with synthesized ctor call + CLike c3 = {NonCStyle(1), 2, 3}; + + outputBuffer[0] = c1.nonCStyleMember.x; + // BUFFER: 1 + outputBuffer[1] = c1.x; + // BUFFER-NEXT: 0 + outputBuffer[2] = c1.y; + // BUFFER-NEXT: 0 + + outputBuffer[3] = c2.nonCStyleMember.x; + // BUFFER-NEXT: 1 + outputBuffer[4] = c2.x; + // BUFFER-NEXT: 2 + outputBuffer[5] = c2.y; + // BUFFER-NEXT: 0 + + outputBuffer[6] = c3.nonCStyleMember.x; + // BUFFER-NEXT: 1 + outputBuffer[7] = c3.x; + // BUFFER-NEXT: 2 + outputBuffer[8] = c3.y; + // BUFFER-NEXT: 3 +} + +[shader("compute")] +void computeMain() +{ + test(); +} diff --git a/tests/initializer-list/generic-array-init.slang b/tests/initializer-list/generic-array-init.slang index 4257e2972..83c14ebd2 100644 --- a/tests/initializer-list/generic-array-init.slang +++ b/tests/initializer-list/generic-array-init.slang @@ -2,7 +2,7 @@ //TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-shaderobj -mtl //TEST(compute):COMPARE_COMPUTE(filecheck-buffer=BUFFER):-cpu -compute -entry computeMain -//TEST_INPUT:ubuffer(data=[9 9 9 9], stride=4):out,name=outputBuffer +//TEST_INPUT:ubuffer(data=[9 9 9 9 9 9 9 9 9 9 9 9], stride=4):out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; void test<let TSize : uint>() @@ -18,6 +18,28 @@ void test<let TSize : uint>() outputBuffer[2] = array[2]; // BUFFER-NEXT: 3 outputBuffer[3] = array.getCount(); + + vector<int, TSize> vec = {}; + + // BUFFER-NEXT: 0 + outputBuffer[4] = vec[0]; + // BUFFER-NEXT: 0 + outputBuffer[5] = vec[1]; + // BUFFER-NEXT: 0 + outputBuffer[6] = vec[2]; + // BUFFER-NEXT: 3 + outputBuffer[7] = vec.getCount(); + + matrix<float, TSize, TSize-1> mat = {}; + + // BUFFER-NEXT: 0 + outputBuffer[8] = (int)mat[0][0]; + // BUFFER-NEXT: 0 + outputBuffer[9] = (int)mat[1][1]; + // BUFFER-NEXT: 0 + outputBuffer[10] = (int)mat[2][1]; + // BUFFER-NEXT: 3 + outputBuffer[11] = mat.getCount(); // this is a bad name, getCount() is actually get the number of row. } [shader("compute")] @@ -25,4 +47,4 @@ void test<let TSize : uint>() void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) { test<3>(); -} +} diff --git a/tests/initializer-list/partial-init.slang b/tests/initializer-list/partial-init.slang index 55f3816fb..a4739f041 100644 --- a/tests/initializer-list/partial-init.slang +++ b/tests/initializer-list/partial-init.slang @@ -8,15 +8,15 @@ struct PartialInit { int x; int y = 1; // compiler synthesizes: - // __init(int x, int y = 1); + // __init(int x = {}, int y = 1); } struct PartialInit2 { int x = 1; int y; - // __init(int x, int y); + // __init(int x, int y = {}); } -//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0], stride=4):out,name=outputBuffer +//TEST_INPUT:ubuffer(data=[0 0 0 0 0 0 0 0 0 0], stride=4):out,name=outputBuffer RWStructuredBuffer<int> outputBuffer; void test() { @@ -38,6 +38,18 @@ void test() outputBuffer[4] = p3.x; // BUFFER-NEXT: 5 outputBuffer[5] = p3.y; + + PartialInit p4 = {}; // calls `__init`, result is {0, 1} + // BUFFER-NEXT: 0 + outputBuffer[6] = p4.x; + // BUFFER-NEXT: 1 + outputBuffer[7] = p4.y; + + PartialInit2 p5 = {}; // calls `__init`, result is {1, 0} + // BUFFER-NEXT: 1 + outputBuffer[8] = p5.x; + // BUFFER-NEXT: 0 + outputBuffer[9] = p5.y; } [shader("compute")] diff --git a/tests/initializer-list/struct-visibility-diagnostic-1.slang b/tests/initializer-list/struct-visibility-diagnostic-1.slang index ab11933ae..1670860ad 100644 --- a/tests/initializer-list/struct-visibility-diagnostic-1.slang +++ b/tests/initializer-list/struct-visibility-diagnostic-1.slang @@ -4,12 +4,8 @@ public struct Visibility { internal int x; public int y = 0; - // the compiler does not synthesize any ctor. - // the compiler will try to synthesize: - // public __init(int y); - // but then it will find that `x` cannot be initialized. - // so this synthesis will fail and no ctor will be added - // to the type. + // will synthesize a constructor + // __init(int y = 0) } void test() diff --git a/tests/initializer-list/struct-visibility-diagnostic-2.slang b/tests/initializer-list/struct-visibility-diagnostic-2.slang index a3255de5e..b9e92555b 100644 --- a/tests/initializer-list/struct-visibility-diagnostic-2.slang +++ b/tests/initializer-list/struct-visibility-diagnostic-2.slang @@ -4,12 +4,8 @@ public struct Visibility { internal int x; public int y = 5; - // the compiler does not synthesize any ctor. - // the compiler will try to synthesize: - // public __init(int y); - // but then it will find that `x` cannot be initialized. - // so this synthesis will fail and no ctor will be added - // to the type. + // will synthesize a constructor + // __init(int y = 0) } void test() diff --git a/tests/initializer-list/struct-visibility-diagnostic-3.slang b/tests/initializer-list/struct-visibility-diagnostic-3.slang index 75ac5919d..e36bd4e4e 100644 --- a/tests/initializer-list/struct-visibility-diagnostic-3.slang +++ b/tests/initializer-list/struct-visibility-diagnostic-3.slang @@ -1,15 +1,13 @@ //DIAGNOSTIC_TEST:SIMPLE(filecheck=CHECK): +public struct NonCStyle +{} public struct Visibility { internal int x; - public int y; - // the compiler does not synthesize any ctor. - // the compiler will try to synthesize: - // public __init(int y); - // but then it will find that `x` cannot be initialized. - // so this synthesis will fail and no ctor will be added - // to the type. + public int[] y; // define a unsized array here on purpose so that the ctor will not associate it with a '{}' initializer + // will synthesize a constructor + // __init(int[] y) } void test() |
