diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-18 17:21:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-18 17:21:48 -0700 |
| commit | 26e25f6e73a9808ad93c98ad34907e3a27b6726c (patch) | |
| tree | e9d8d024bf927bd0f8e1ed5f7c5fcbfb9c3bd21c | |
| parent | f96a3fea6704da866e96e453f722a951c214ba28 (diff) | |
Check for cylic types. (#3790)
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj | 2 | ||||
| -rw-r--r-- | build/visual-studio/slang/slang.vcxproj.filters | 6 | ||||
| -rw-r--r-- | source/slang/slang-diagnostic-defs.h | 2 | ||||
| -rw-r--r-- | source/slang/slang-ir-check-recursive-type.cpp | 59 | ||||
| -rw-r--r-- | source/slang/slang-ir-check-recursive-type.h | 11 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 4 | ||||
| -rw-r--r-- | tests/bugs/cyclic-type.slang | 21 |
7 files changed, 105 insertions, 0 deletions
diff --git a/build/visual-studio/slang/slang.vcxproj b/build/visual-studio/slang/slang.vcxproj index c503e8f4d..aca22890b 100644 --- a/build/visual-studio/slang/slang.vcxproj +++ b/build/visual-studio/slang/slang.vcxproj @@ -373,6 +373,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla <ClInclude Include="..\..\..\source\slang\slang-ir-bit-field-accessors.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-byte-address-legalize.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-check-differentiability.h" />
+ <ClInclude Include="..\..\..\source\slang\slang-ir-check-recursive-type.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-cleanup-void.h" />
<ClInclude Include="..\..\..\source\slang\slang-ir-clone.h" />
@@ -598,6 +599,7 @@ IF EXIST ..\..\..\external\slang-glslang\bin\windows-aarch64\release\slang-glsla <ClCompile Include="..\..\..\source\slang\slang-ir-bit-field-accessors.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-byte-address-legalize.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-check-differentiability.cpp" />
+ <ClCompile Include="..\..\..\source\slang\slang-ir-check-recursive-type.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-cleanup-void.cpp" />
<ClCompile Include="..\..\..\source\slang\slang-ir-clone.cpp" />
diff --git a/build/visual-studio/slang/slang.vcxproj.filters b/build/visual-studio/slang/slang.vcxproj.filters index 9c274990d..7b6b7de2c 100644 --- a/build/visual-studio/slang/slang.vcxproj.filters +++ b/build/visual-studio/slang/slang.vcxproj.filters @@ -207,6 +207,9 @@ <ClInclude Include="..\..\..\source\slang\slang-ir-check-differentiability.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\source\slang\slang-ir-check-recursive-type.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -878,6 +881,9 @@ <ClCompile Include="..\..\..\source\slang\slang-ir-check-differentiability.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\source\slang\slang-ir-check-recursive-type.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\..\..\source\slang\slang-ir-check-unsupported-inst.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index ba57e63f9..7a72daa5e 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -691,6 +691,7 @@ DIAGNOSTIC(40010, Note, seeInterfaceUsage, "see usage of interface '$0'.") DIAGNOSTIC(40011, Error, unconstrainedGenericParameterNotAllowedInDynamicFunction, "unconstrained generic paramter '$0' is not allowed in a dynamic function.") + DIAGNOSTIC(40020, Error, cannotUnrollLoop, "loop does not terminate within the limited number of iterations, unrolling is aborted.") DIAGNOSTIC(40030, Fatal, functionNeverReturnsFatal, "function '$0' never returns, compilation ceased.") @@ -698,6 +699,7 @@ DIAGNOSTIC(40030, Fatal, functionNeverReturnsFatal, "function '$0' never returns // 41000 - IR-level validation issues DIAGNOSTIC(41000, Warning, unreachableCode, "unreachable code detected") +DIAGNOSTIC(41001, Error, recursiveType, "type '$0' contains cyclic reference to itself.") DIAGNOSTIC(41010, Warning, missingReturn, "control flow may reach end of non-'void' function") DIAGNOSTIC(41015, Error, usingUninitializedValue, "use of uninitialized value '$0'") diff --git a/source/slang/slang-ir-check-recursive-type.cpp b/source/slang/slang-ir-check-recursive-type.cpp new file mode 100644 index 000000000..8679801d0 --- /dev/null +++ b/source/slang/slang-ir-check-recursive-type.cpp @@ -0,0 +1,59 @@ +#include "slang-ir-check-recursive-type.h" +#include "slang-ir-util.h" + +namespace Slang +{ + bool checkTypeRecursionImpl(HashSet<IRInst*>& checkedTypes, HashSet<IRInst*>& stack, IRInst* type, IRInst* field, DiagnosticSink* sink) + { + auto visitElementType = [&](IRInst* elementType, IRInst* field) -> bool + { + if (!stack.add(elementType)) + { + sink->diagnose(field ? field : type, Diagnostics::recursiveType, type); + return false; + } + if (checkedTypes.add(elementType)) + checkTypeRecursionImpl(checkedTypes, stack, elementType, field, sink); + stack.remove(elementType); + return true; + }; + if (auto arrayType = as<IRArrayTypeBase>(type)) + { + return visitElementType(arrayType->getElementType(), field); + } + else if (auto structType = as<IRStructType>(type)) + { + for (auto sfield : structType->getFields()) + if (!visitElementType(sfield->getFieldType(), sfield)) + return false; + } + return true; + } + + void checkTypeRecursion(HashSet<IRInst*>& checkedTypes, IRInst* type, DiagnosticSink* sink) + { + HashSet<IRInst*> stack; + if (checkedTypes.add(type)) + { + stack.add(type); + checkTypeRecursionImpl(checkedTypes, stack, type, nullptr, sink); + } + } + + void checkForRecursiveTypes(IRModule* module, DiagnosticSink* sink) + { + HashSet<IRInst*> checkedTypes; + for (auto globalInst : module->getGlobalInsts()) + { + switch (globalInst->getOp()) + { + case kIROp_StructType: + { + checkTypeRecursion(checkedTypes, globalInst, sink); + } + break; + } + } + } + +} diff --git a/source/slang/slang-ir-check-recursive-type.h b/source/slang/slang-ir-check-recursive-type.h new file mode 100644 index 000000000..0ab911e79 --- /dev/null +++ b/source/slang/slang-ir-check-recursive-type.h @@ -0,0 +1,11 @@ +#pragma once + +namespace Slang +{ + struct IRModule; + class DiagnosticSink; + + void checkForRecursiveTypes( + IRModule* module, + DiagnosticSink* sink); +} diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 4e564f703..5a3b0c2c5 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -20,6 +20,7 @@ #include "slang-ir-insts.h" #include "slang-ir-insert-debug-value-store.h" #include "slang-ir-check-differentiability.h" +#include "slang-ir-check-recursive-type.h" #include "slang-ir-missing-return.h" #include "slang-ir-sccp.h" #include "slang-ir-ssa.h" @@ -10665,6 +10666,9 @@ RefPtr<IRModule> generateIRForTranslationUnit( checkForMissingReturns(module, compileRequest->getSink()); + // We don't allow recursive types. + checkForRecursiveTypes(module, compileRequest->getSink()); + // Check for invalid differentiable function body. checkAutoDiffUsages(module, compileRequest->getSink()); diff --git a/tests/bugs/cyclic-type.slang b/tests/bugs/cyclic-type.slang new file mode 100644 index 000000000..49591fbe6 --- /dev/null +++ b/tests/bugs/cyclic-type.slang @@ -0,0 +1,21 @@ + +//TEST:SIMPLE(filecheck=CHECK):-target spirv -emit-spirv-directly + +// CHECK: error 41001: + +struct TA +{ + TB tb; +} + +struct TB +{ + TA ta[2]; +} + +[numthreads(1,1,1)] +void main() +{ + TA ta; + ta.tb.ta[0] = ta; +}
\ No newline at end of file |
