diff options
| author | Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> | 2024-08-07 02:04:37 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-07 02:04:37 -0400 |
| commit | 2f2ae8c31490ab01ce0d0cc76d5d7fcf1d21efe7 (patch) | |
| tree | 135cb2109f2717dba3a11929c4cdf163b5ad5c50 /tools | |
| parent | 366c9b4526b4b940c8aafce459d6784211e862bc (diff) | |
More reflection API features. (#4740)
* More reflection API features.
+ Lookup methods and members (by string) on types
+ Fix issue with looking up non-static members through the scope operator '::'
+ `GenericReflection`: Cast a decl to generic to access unspecialized generic parameter names and constraints
+ `GenericReflection`: Use `getGenericContainer()` from function, variable or type to access the 'nearest' generic parent along with specialization info
+ `GenericReflection::getConcreteType` and `GenericReflection::getConcreteIntVal`: to get the concrete type of a param in the context of the reflection object
+ `GenericReflection::getOuterGenericContainer` to go up one level and get the outer generic declarations (if there are more than one enclosing generic scopes)
+ `DeclReflection::getParent`: go to parent declaration.
+ Change `VariableReflection` to be a `DeclRef` rather than a decl (allows us to return properly substituted types for methods, members, and more)
* Fix Falcor issue
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/slang-unit-test/unit-test-decl-tree-reflection.cpp | 139 |
1 files changed, 135 insertions, 4 deletions
diff --git a/tools/slang-unit-test/unit-test-decl-tree-reflection.cpp b/tools/slang-unit-test/unit-test-decl-tree-reflection.cpp index e443358fb..fb35f323c 100644 --- a/tools/slang-unit-test/unit-test-decl-tree-reflection.cpp +++ b/tools/slang-unit-test/unit-test-decl-tree-reflection.cpp @@ -52,6 +52,24 @@ SLANG_UNIT_TEST(declTreeReflection) { return pos; } + + uint f(uint y) { return y; } + + struct MyType + { + int x; + float f(float x) { return x; } + } + + struct MyGenericType<T : IArithmetic & IFloat> + { + T z; + T g() { return z; } + U h<U>(U x, out T y) { y = z; return x; } + + T j<let N : int>(T x, out int o) { o = N; return x; } + } + )"; auto moduleName = "moduleG" + String(Process::getId()); @@ -75,10 +93,15 @@ SLANG_UNIT_TEST(declTreeReflection) module->findAndCheckEntryPoint("fragMain", SLANG_STAGE_FRAGMENT, entryPoint.writeRef(), diagnosticBlob.writeRef()); SLANG_CHECK(entryPoint != nullptr); + ComPtr<slang::IComponentType> compositeProgram; + slang::IComponentType* components[] = { module, entryPoint.get() }; + session->createCompositeComponentType(components, 2, compositeProgram.writeRef(), diagnosticBlob.writeRef()); + SLANG_CHECK(compositeProgram != nullptr); + auto moduleDeclReflection = module->getModuleReflection(); SLANG_CHECK(moduleDeclReflection != nullptr); SLANG_CHECK(moduleDeclReflection->getKind() == slang::DeclReflection::Kind::Module); - SLANG_CHECK(moduleDeclReflection->getChildrenCount() == 4); + SLANG_CHECK(moduleDeclReflection->getChildrenCount() == 7); // First declaration should be a struct with 1 variable auto firstDecl = moduleDeclReflection->getChild(0); @@ -86,7 +109,7 @@ SLANG_UNIT_TEST(declTreeReflection) SLANG_CHECK(firstDecl->getChildrenCount() == 1); { - slang::TypeReflection* type = firstDecl->getType(globalSession); + slang::TypeReflection* type = firstDecl->getType(); SLANG_CHECK(getTypeFullName(type) == "MyFuncPropertyAttribute"); // Check the field of the struct. @@ -140,6 +163,107 @@ SLANG_UNIT_TEST(declTreeReflection) SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "vector<float,4>"); } + // Sixth declaration should be a generic struct + auto sixthDecl = moduleDeclReflection->getChild(5); + SLANG_CHECK(sixthDecl->getKind() == slang::DeclReflection::Kind::Generic); + auto genericReflection = sixthDecl->asGeneric(); + SLANG_CHECK(genericReflection->getTypeParameterCount() == 1); + auto typeParamT = genericReflection->getTypeParameter(0); + SLANG_CHECK(UnownedStringSlice(typeParamT->getName()) == "T"); + auto typeParamTConstraintCount = genericReflection->getTypeParameterConstraintCount(typeParamT); + SLANG_CHECK(typeParamTConstraintCount == 2); + auto typeParamTConstraintType1 = genericReflection->getTypeParameterConstraintType(typeParamT, 0); + SLANG_CHECK(getTypeFullName(typeParamTConstraintType1) == "IArithmetic"); + auto typeParamTConstraintType2 = genericReflection->getTypeParameterConstraintType(typeParamT, 1); + SLANG_CHECK(getTypeFullName(typeParamTConstraintType2) == "IFloat"); + + auto innerStruct = genericReflection->getInnerDecl(); + SLANG_CHECK(innerStruct->getKind() == slang::DeclReflection::Kind::Struct); + + + // Check type-lookup-by-name + { + auto type = compositeProgram->getLayout()->findTypeByName("MyType"); + SLANG_CHECK(type != nullptr); + //SLANG_CHECK(type->getKind() == slang::DeclReflection::Kind::Struct); + SLANG_CHECK(UnownedStringSlice(type->getName()) == "MyType"); + auto funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "f"); + SLANG_CHECK(funcReflection != nullptr); + SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "f"); + SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "float"); + SLANG_CHECK(funcReflection->getParameterCount() == 1); + SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "x"); + SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "float"); + } + + // Check type-lookup-by-name for generic type + { + auto type = compositeProgram->getLayout()->findTypeByName("MyGenericType<half>"); + SLANG_CHECK(type != nullptr); + //SLANG_CHECK(type->getKind() == slang::DeclReflection::Kind::Struct); + SLANG_CHECK(getTypeFullName(type) == "MyGenericType<half>"); + auto funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "g"); + SLANG_CHECK(funcReflection != nullptr); + SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "g"); + SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "half"); + SLANG_CHECK(funcReflection->getParameterCount() == 0); + + auto varReflection = compositeProgram->getLayout()->findVarByNameInType(type, "z"); + SLANG_CHECK(varReflection != nullptr); + SLANG_CHECK(UnownedStringSlice(varReflection->getName()) == "z"); + SLANG_CHECK(getTypeFullName(varReflection->getType()) == "half"); + + funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "h<float>"); + SLANG_CHECK(funcReflection != nullptr); + SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "h"); + SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "float"); + SLANG_CHECK(funcReflection->getParameterCount() == 2); + SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "x"); + SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "float"); + SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(1)->getName()) == "y"); + SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(1)->getType()) == "half"); + + // Access parent generic container from a specialized method. + auto specializationInfo = funcReflection->getGenericContainer(); + SLANG_CHECK(specializationInfo != nullptr); + SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "h"); + SLANG_CHECK(specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic); + // Check type parameters + SLANG_CHECK(specializationInfo->getTypeParameterCount() == 1); + auto typeParam = specializationInfo->getTypeParameter(0); + SLANG_CHECK(UnownedStringSlice(typeParam->getName()) == "U"); // generic name + SLANG_CHECK(getTypeFullName(specializationInfo->getConcreteType(typeParam)) == "float"); // specialized type name under the context in which the generic is obtained + SLANG_CHECK(specializationInfo->getTypeParameterConstraintCount(typeParam) == 0); + + // Go up another level to the generic struct + specializationInfo = specializationInfo->getOuterGenericContainer(); + SLANG_CHECK(specializationInfo != nullptr); + SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "MyGenericType"); + SLANG_CHECK(specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic); + // Check type parameters + SLANG_CHECK(specializationInfo->getTypeParameterCount() == 1); + typeParam = specializationInfo->getTypeParameter(0); + SLANG_CHECK(UnownedStringSlice(typeParam->getName()) == "T"); // generic name + SLANG_CHECK(getTypeFullName(specializationInfo->getConcreteType(typeParam)) == "half"); // specialized type name under the context in which the generic is obtained + SLANG_CHECK(specializationInfo->getTypeParameterConstraintCount(typeParam) == 2); + + // Query 'j' on the type 'half' + funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "j<10>"); + SLANG_CHECK(funcReflection != nullptr); + SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "j"); + + // Check the generic parameters + specializationInfo = funcReflection->getGenericContainer(); + SLANG_CHECK(specializationInfo != nullptr); + SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "j"); + SLANG_CHECK(specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic); + SLANG_CHECK(specializationInfo->getValueParameterCount() == 1); + auto valueParam = specializationInfo->getValueParameter(0); + SLANG_CHECK(UnownedStringSlice(valueParam->getName()) == "N"); // generic name + SLANG_CHECK(specializationInfo->getConcreteIntVal(valueParam) == 10); + } + + // Check iterators { unsigned int count = 0; @@ -147,20 +271,27 @@ SLANG_UNIT_TEST(declTreeReflection) { count++; } - SLANG_CHECK(count == 4); + SLANG_CHECK(count == 7); count = 0; for (auto* child : moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Func>()) { count++; } - SLANG_CHECK(count == 2); + SLANG_CHECK(count == 3); count = 0; for (auto* child : moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Struct>()) { count++; } + SLANG_CHECK(count == 2); + + count = 0; + for (auto* child : moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Generic>()) + { + count++; + } SLANG_CHECK(count == 1); } } |
