diff options
| author | Jay Kwak <82421531+jkwak-work@users.noreply.github.com> | 2025-01-23 00:06:21 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-23 00:06:21 -0800 |
| commit | a9ce7520e5f1b97b09e5de69455258bef55e10d2 (patch) | |
| tree | ab9af31ba0a52cd4dd245e19fa4323864286f551 | |
| parent | 8000e0ede34e920cc7f37d69a335d74a472eff42 (diff) | |
Fix incorrect resolve of specialization instance (#6162)
* Fix incorrect resolve of specialization instance
While checking the uninitialized variables, we were not resolving the
specialized instance correctly. This commit repeats the resolve while
the result is a specialization instance. A new test is added for this:
tests/diagnostics/uninitialized-generic.slang
After the problem is fixed, it revealed another problem in existing
tests:
tests/compute/nested-generics2.slang
tests/diagnostics/uninitialized-local-variables.slang
When a struct has a member variable whose type is a generic type,
we cannot iterate over its member variables yet, because the type
is unknown until the generic function/struct is specialized. We will
have to give up checking for these cases.
| -rw-r--r-- | source/slang/slang-ir-use-uninitialized-values.cpp | 15 | ||||
| -rw-r--r-- | tests/diagnostics/uninitialized-generic.slang | 30 | ||||
| -rw-r--r-- | tests/diagnostics/uninitialized-local-variables.slang | 9 |
3 files changed, 41 insertions, 13 deletions
diff --git a/source/slang/slang-ir-use-uninitialized-values.cpp b/source/slang/slang-ir-use-uninitialized-values.cpp index b1db2913e..51de2117c 100644 --- a/source/slang/slang-ir-use-uninitialized-values.cpp +++ b/source/slang/slang-ir-use-uninitialized-values.cpp @@ -139,13 +139,6 @@ static bool isDifferentiableFunc(IRInst* func) return false; } -static IRInst* resolveSpecialization(IRSpecialize* spec) -{ - IRInst* base = spec->getBase(); - IRGeneric* generic = as<IRGeneric>(base); - return findInnerMostGenericReturnVal(generic); -} - // The `upper` field contains the struct that the type is // is contained in. It is used to check for empty structs. static bool canIgnoreType(IRType* type, IRType* upper) @@ -174,6 +167,10 @@ static bool canIgnoreType(IRType* type, IRType* upper) if (as<IRInterfaceType>(type)) return true; + // We don't know what type it will be yet. + if (as<IRParam>(type)) + return true; + // For pointers, check the value type (primarily for globals) if (auto ptr = as<IRPtrType>(type)) { @@ -188,7 +185,7 @@ static bool canIgnoreType(IRType* type, IRType* upper) // In the case of specializations, check returned type if (auto spec = as<IRSpecialize>(type)) { - IRInst* inner = resolveSpecialization(spec); + IRInst* inner = getResolvedInstForDecorations(spec); IRType* innerType = as<IRType>(inner); return canIgnoreType(innerType, upper); } @@ -231,7 +228,7 @@ static InstructionUsageType getCallUsageType(IRCall* call, IRInst* inst) IRFunc* ftn = nullptr; IRFuncType* ftype = nullptr; if (auto spec = as<IRSpecialize>(callee)) - ftn = as<IRFunc>(resolveSpecialization(spec)); + ftn = as<IRFunc>(getResolvedInstForDecorations(spec)); // Differentiable functions are mostly ignored, treated as having inout parameters else if (as<IRForwardDifferentiate>(callee)) diff --git a/tests/diagnostics/uninitialized-generic.slang b/tests/diagnostics/uninitialized-generic.slang new file mode 100644 index 000000000..2d6ccd45b --- /dev/null +++ b/tests/diagnostics/uninitialized-generic.slang @@ -0,0 +1,30 @@ +//TEST:SIMPLE(filecheck=CHK): -target spirv -entry computeMain + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<float> outputBuffer; + +groupshared float4 gsVar; + +__generic<TYPE1 : __BuiltinArithmeticType> +struct MyContainer +{ + __generic<TYPE2 : __BuiltinArithmeticType> + void store(__ref vector<TYPE2,4> v) + { + v[0] = TYPE2(0); + v[1] = TYPE2(1); + v[2] = TYPE2(2); + v[3] = TYPE2(3); + } +}; + +[Shader("compute")] +[NumThreads(1, 1, 1)] +void computeMain(int3 dispatchThreadID : SV_DispatchThreadID) +{ + MyContainer<float> obj; + obj.store(gsVar); + + // CHK-NOT:warning 41017: + outputBuffer[0] = gsVar.x; +} diff --git a/tests/diagnostics/uninitialized-local-variables.slang b/tests/diagnostics/uninitialized-local-variables.slang index f7a8ff2c7..9ade4591a 100644 --- a/tests/diagnostics/uninitialized-local-variables.slang +++ b/tests/diagnostics/uninitialized-local-variables.slang @@ -38,13 +38,14 @@ int use_undefined_value(int k) return x; } -// Returning uninitialized values +// We don't know the exact type of T yet. +// T may not have any members, and it may not need any initialization. __generic<T> T generic_undefined_return() { - T x; - //CHK-DAG: warning 41016: use of uninitialized variable 'x' - return x; + T y; + //CHK-NOT: warning 41016: use of uninitialized variable 'y' + return y; } // Array variables |
