summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com>2024-08-07 02:04:37 -0400
committerGitHub <noreply@github.com>2024-08-07 02:04:37 -0400
commit2f2ae8c31490ab01ce0d0cc76d5d7fcf1d21efe7 (patch)
tree135cb2109f2717dba3a11929c4cdf163b5ad5c50 /tools
parent366c9b4526b4b940c8aafce459d6784211e862bc (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.cpp139
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);
}
}