diff options
| author | Yong He <yonghe@outlook.com> | 2024-07-11 16:12:41 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-11 16:12:41 -0700 |
| commit | 24f8999c892a9c4d108616c08d714e8dea562707 (patch) | |
| tree | c3632963f8a940503b46ae2d82b70fedaaf0e1db | |
| parent | 977e4b21d69406b0b68c5963f50489d7433db830 (diff) | |
Fix incorrect codegen when returning initializer list as existential value. (#4618)
* Add `dev` cmake preset.
* Fix incorrect codegen when returning initializer list as existential value.
* Fix cmake.
* Fixup.
| -rw-r--r-- | CMakePresets.json | 9 | ||||
| -rw-r--r-- | docs/building.md | 4 | ||||
| -rw-r--r-- | source/slang/slang-check-conversion.cpp | 41 | ||||
| -rw-r--r-- | tests/language-feature/interfaces/default-construct-conformance.slang | 190 |
4 files changed, 224 insertions, 20 deletions
diff --git a/CMakePresets.json b/CMakePresets.json index 08f85a37f..cd516c8ea 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -38,6 +38,15 @@ "generator": "Visual Studio 17 2022" }, { + "name": "vs2022-dev", + "inherits": "msvc-base", + "description": "Visual Studio 2022 project with debug assisting features", + "generator": "Visual Studio 17 2022", + "cacheVariables": { + "SLANG_ENABLE_IR_BREAK_ALLOC": "TRUE" + } + }, + { "name": "slang-llvm", "inherits": "default", "description": "Build slang-llvm from the system LLVM", diff --git a/docs/building.md b/docs/building.md index a42f4cde6..2b2435302 100644 --- a/docs/building.md +++ b/docs/building.md @@ -40,11 +40,13 @@ cmake --build --preset release # or --preset debug For Visual Studio run: ```bash -cmake --preset vs2022 # or --preset vs2019 +cmake --preset vs2022 # or 'vs2019' or `vs2022-dev` start devenv ./build/slang.sln # to optionally open the project in Visual Studio cmake --build --preset release # to build from the CLI ``` +The `vs2022-dev` preset turns on features that makes debugging easy. + ## Testing ```bash diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp index 16f413055..111f4e465 100644 --- a/source/slang/slang-check-conversion.cpp +++ b/source/slang/slang-check-conversion.cpp @@ -842,29 +842,32 @@ namespace Slang // Coercion from an initializer list is allowed for many types, // so we will farm that out to its own subroutine. // - if( auto fromInitializerListExpr = as<InitializerListExpr>(fromExpr)) + if (fromExpr && as<InitializerListType>(fromExpr->type.type)) { - if( !_coerceInitializerList( - toType, - outToExpr, - fromInitializerListExpr) ) + if (auto fromInitializerListExpr = as<InitializerListExpr>(fromExpr)) { - return false; - } + if (!_coerceInitializerList( + toType, + outToExpr, + fromInitializerListExpr)) + { + return false; + } - // For now, we treat coercion from an initializer list - // as having no cost, so that all conversions from initializer - // lists are equally valid. This is fine given where initializer - // lists are allowed to appear now, but might need to be made - // more strict if we allow for initializer lists in more - // places in the language (e.g., as function arguments). - // - if(outCost) - { - *outCost = kConversionCost_None; - } + // For now, we treat coercion from an initializer list + // as having no cost, so that all conversions from initializer + // lists are equally valid. This is fine given where initializer + // lists are allowed to appear now, but might need to be made + // more strict if we allow for initializer lists in more + // places in the language (e.g., as function arguments). + // + if (outCost) + { + *outCost = kConversionCost_None; + } - return true; + return true; + } } // nullptr_t can be cast into any pointer type. diff --git a/tests/language-feature/interfaces/default-construct-conformance.slang b/tests/language-feature/interfaces/default-construct-conformance.slang new file mode 100644 index 000000000..00778a9f6 --- /dev/null +++ b/tests/language-feature/interfaces/default-construct-conformance.slang @@ -0,0 +1,190 @@ +//TEST:SIMPLE(filecheck=CHECK): -target hlsl -entry testMain -profile cs_6_0 + +// Test that invoking the default constructor of a type then use the result as an existential value +// works correctly. + +RWStructuredBuffer<uint> output; +RWStructuredBuffer<uint> expected; + +interface ITest +{ + uint getValue(); +}; + + +//TEST_INPUT:type_conformance Test0:ITest = 0 +struct Test0 : ITest +{ + uint getValue() { return 0; } +}; + +//TEST_INPUT:type_conformance Test1:ITest = 1 +struct Test1 : ITest +{ + uint getValue() { return 1; } +}; + +//TEST_INPUT:type_conformance TestAny:ITest = 2 +struct TestAny : ITest +{ + uint value = 5; + __init(uint v) + { + value = v; + } + + uint getValue() { return value; } +} + +// CHECK: Tuple{{.*}} makeTest0{{.*}}() +// CHECK: Tuple{{.*}} = { uint2(0U, 0U), uint2(0U, 0U), packAnyValue4{{.*}} }; +ITest makeTest0() +{ + return Test0(); +} + +// CHECK: Tuple{{.*}} makeTest1{{.*}}() +// CHECK: Tuple{{.*}} = { uint2(0U, 0U), uint2(1U, 0U), packAnyValue4{{.*}} }; +ITest makeTest1() +{ + return Test1(); +} + +// CHECK: Tuple{{.*}} makeTestAny{{.*}}() +// CHECK: Tuple{{.*}} = { uint2(0U, 0U), uint2(2U, 0U), packAnyValue4{{.*}} }; +ITest makeTestAny() +{ + return TestAny(); +} + +ITest makeTestAny(uint v) +{ + return TestAny(v); +} + + +[numthreads(16, 1, 1)] +void testMain(uint3 threadID: SV_DispatchThreadID) +{ + if (threadID.x != 0) + return; + + int outputIdx = 0; + + /// Test0 + { + Test0 test; + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 0; + } + + { + ITest test = Test0(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 0; + } + + { + output[outputIdx] = Test0().getValue(); + expected[outputIdx++] = 0; + } + + { + ITest test = makeTest0(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 0; + } + + { + output[outputIdx] = makeTest0().getValue(); + expected[outputIdx++] = 0; + } + + output[outputIdx] = 1000; + expected[outputIdx++] = 1000; + + /// Test1 + { + Test1 test; + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 1; + } + + { + ITest test = Test1(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 1; + } + + { + output[outputIdx] = Test1().getValue(); + expected[outputIdx++] = 1; + } + + { + ITest test = makeTest1(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 1; + } + + { + output[outputIdx] = makeTest1().getValue(); + expected[outputIdx++] = 1; + } + + output[outputIdx] = 2000; + expected[outputIdx++] = 2000; + + /// TestAny + { + TestAny test; + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 5; + } + + { + ITest test = TestAny(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 5; + } + + { + ITest test = TestAny(2); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 2; + } + + { + output[outputIdx] = TestAny().getValue(); + expected[outputIdx++] = 5; + } + + { + output[outputIdx] = TestAny(2).getValue(); + expected[outputIdx++] = 2; + } + + { + ITest test = makeTestAny(); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 5; + } + + { + ITest test = makeTestAny(2); + output[outputIdx] = test.getValue(); + expected[outputIdx++] = 2; + } + + { + output[outputIdx] = makeTestAny().getValue(); + expected[outputIdx++] = 5; + } + + { + output[outputIdx] = makeTestAny(2).getValue(); + expected[outputIdx++] = 2; + } + + expected[outputIdx++] = uint(-1); +}
\ No newline at end of file |
