From 2f2ae8c31490ab01ce0d0cc76d5d7fcf1d21efe7 Mon Sep 17 00:00:00 2001 From: Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> Date: Wed, 7 Aug 2024 02:04:37 -0400 Subject: 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 --- source/slang/slang-reflection-api.cpp | 342 +++++++++++++++++++++++++++++++--- 1 file changed, 318 insertions(+), 24 deletions(-) (limited to 'source/slang/slang-reflection-api.cpp') diff --git a/source/slang/slang-reflection-api.cpp b/source/slang/slang-reflection-api.cpp index a212f0d1b..edfd27489 100644 --- a/source/slang/slang-reflection-api.cpp +++ b/source/slang/slang-reflection-api.cpp @@ -8,6 +8,7 @@ #include "slang-compiler.h" #include "slang-type-layout.h" #include "slang-syntax.h" +#include "slang-check.h" #include // Don't signal errors for stuff we don't implement here, @@ -55,14 +56,14 @@ static inline SpecializationParamLayout* convert(SlangReflectionTypeParameter * return (SpecializationParamLayout*) typeParam; } -static inline Decl* convert(SlangReflectionVariable* var) +static inline DeclRef convert(SlangReflectionVariable* var) { - return (Decl*) var; + return DeclRef((DeclRefBase*) var); } -static inline SlangReflectionVariable* convert(Decl* var) +static inline SlangReflectionVariable* convert(DeclRef var) { - return (SlangReflectionVariable*) var; + return (SlangReflectionVariable*) var.declRefBase; } static inline DeclRef convert(SlangReflectionFunction* func) @@ -76,6 +77,17 @@ static inline SlangReflectionFunction* convert(DeclRef func) return (SlangReflectionFunction*)func.declRefBase; } +static inline DeclRef convertGenericToDeclRef(SlangReflectionGeneric* func) +{ + DeclRefBase* declBase = (DeclRefBase*)func; + return DeclRef(declBase); +} + +static inline SlangReflectionGeneric* convertDeclToGeneric(DeclRef func) +{ + return (SlangReflectionGeneric*)func.declRefBase; +} + static inline VarLayout* convert(SlangReflectionVariableLayout* var) { return (VarLayout*) var; @@ -482,7 +494,7 @@ SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex(SlangReflect auto fields = getFields( getModule(declRef.getDecl())->getLinkage()->getASTBuilder(), structDeclRef, MemberFilterStyle::Instance); auto fieldDeclRef = fields[index]; - return (SlangReflectionVariable*) fieldDeclRef.getDecl(); + return convert(fieldDeclRef); } } @@ -786,6 +798,52 @@ SLANG_API SlangReflectionFunction* spReflection_FindFunctionByName(SlangReflecti return nullptr; } +SLANG_API SlangReflectionFunction* spReflection_FindFunctionByNameInType(SlangReflection* reflection, SlangReflectionType* reflType, char const* name) +{ + auto programLayout = convert(reflection); + auto program = programLayout->getProgram(); + + auto type = convert(reflType); + + Slang::DiagnosticSink sink( + programLayout->getTargetReq()->getLinkage()->getSourceManager(), + Lexer::sourceLocationLexer); + + try + { + auto result = program->findDeclFromStringInType(type, name, LookupMask::Function, &sink); + if (auto funcDeclRef = result.as()) + return convert(funcDeclRef); + } + catch (...) + { + } + return nullptr; +} + +SLANG_API SlangReflectionVariable* spReflection_FindVarByNameInType(SlangReflection* reflection, SlangReflectionType* reflType, char const* name) +{ + auto programLayout = convert(reflection); + auto program = programLayout->getProgram(); + + auto type = convert(reflType); + + Slang::DiagnosticSink sink( + programLayout->getTargetReq()->getLinkage()->getSourceManager(), + Lexer::sourceLocationLexer); + + try + { + auto result = program->findDeclFromStringInType(type, name, LookupMask::Value, &sink); + if (auto varDeclRef = result.as()) + return convert(varDeclRef.as()); + } + catch (...) + { + } + return nullptr; +} + SLANG_API SlangReflectionType * spReflection_FindTypeByName(SlangReflection * reflection, char const * name) { auto programLayout = convert(reflection); @@ -811,6 +869,35 @@ SLANG_API SlangReflectionType * spReflection_FindTypeByName(SlangReflection * re } } +SlangReflectionGeneric* getInnermostGenericParent(DeclRef declRef) +{ + auto decl = declRef.getDecl(); + auto astBuilder = getModule(decl)->getLinkage()->getASTBuilder(); + auto parentDecl = decl; + while(parentDecl) + { + if(parentDecl->parentDecl && as(parentDecl->parentDecl)) + return convertDeclToGeneric( + substituteDeclRef( + SubstitutionSet(declRef), + astBuilder, + createDefaultSubstitutionsIfNeeded(astBuilder, nullptr, DeclRef(parentDecl)))); + parentDecl = parentDecl->parentDecl; + } + + return nullptr; +} + +SLANG_API SlangReflectionGeneric* spReflectionType_GetGenericContainer(SlangReflectionType* type) +{ + auto declRefType = as(convert(type)); + if (!declRefType) + return nullptr; + + auto declRef = declRefType->getDeclRef(); + return getInnermostGenericParent(declRef); +} + SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout( SlangReflection* reflection, SlangReflectionType* inType, @@ -2228,7 +2315,7 @@ SLANG_API SlangReflectionVariable* spReflectionTypeLayout_getBindingRangeLeafVar return 0; auto& bindingRange = extTypeLayout->m_bindingRanges[index]; - return convert(bindingRange.leafVariable); + return convert(DeclRef(bindingRange.leafVariable)); } @@ -2571,7 +2658,7 @@ SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeDescriptorRangeSpaceO SLANG_API char const* spReflectionVariable_GetName(SlangReflectionVariable* inVar) { - auto var = convert(inVar); + auto var = convert(inVar).getDecl(); if (as(var)) return "$base"; @@ -2589,17 +2676,26 @@ SLANG_API SlangReflectionType* spReflectionVariable_GetType(SlangReflectionVaria { auto var = convert(inVar); - if (auto inheritanceDecl = as(var)) - return convert(inheritanceDecl->base.type); - if(!var) return nullptr; - return convert(as(var)->getType()); + auto astBuilder = getModule(var.getDecl())->getLinkage()->getASTBuilder(); + + if (auto inheritanceDecl = as(var.getDecl())) + return convert(inheritanceDecl->base.type); + + if (auto varDecl = as(var.getDecl())) + return convert( + substituteType( + SubstitutionSet(var), + astBuilder, + varDecl->getType())); + + return nullptr; } SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier(SlangReflectionVariable* inVar, SlangModifierID modifierID) { - auto var = convert(inVar); + auto var = convert(inVar).getDecl(); if(!var) return nullptr; @@ -2648,26 +2744,26 @@ SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier(SlangReflec SLANG_API unsigned int spReflectionVariable_GetUserAttributeCount(SlangReflectionVariable* inVar) { - auto varDecl = convert(inVar); + auto varDecl = convert(inVar).getDecl(); if (!varDecl) return 0; return getUserAttributeCount(varDecl); } SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute(SlangReflectionVariable* inVar, unsigned int index) { - auto varDecl = convert(inVar); + auto varDecl = convert(inVar).getDecl(); if (!varDecl) return 0; return getUserAttributeByIndex(varDecl, index); } SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName(SlangReflectionVariable* inVar, SlangSession* session, char const* name) { - auto varDecl = convert(inVar); + auto varDecl = convert(inVar).getDecl(); if (!varDecl) return 0; return findUserAttributeByName(asInternal(session), varDecl, name); } SLANG_API bool spReflectionVariable_HasDefaultValue(SlangReflectionVariable* inVar) { - auto decl = convert(inVar); + auto decl = convert(inVar).getDecl(); if (auto varDecl = as(decl)) { return varDecl->initExpr != nullptr; @@ -2676,6 +2772,12 @@ SLANG_API bool spReflectionVariable_HasDefaultValue(SlangReflectionVariable* inV return false; } +SLANG_API SlangReflectionGeneric* spReflectionVariable_GetGenericContainer(SlangReflectionVariable* var) +{ + auto declRef = convert(var); + return getInnermostGenericParent(declRef); +} + // Variable Layout Reflection SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable(SlangReflectionVariableLayout* inVarLayout) @@ -2683,7 +2785,7 @@ SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable(SlangR auto varLayout = convert(inVarLayout); if(!varLayout) return nullptr; - return (SlangReflectionVariable*)(varLayout->varDecl.getDecl()); + return convert(varLayout->varDecl); } SLANG_API SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout(SlangReflectionVariableLayout* inVarLayout) @@ -2850,7 +2952,7 @@ SLANG_API SlangReflectionType* spReflectionFunction_GetResultType(SlangReflectio SLANG_API SlangReflectionModifier* spReflectionFunction_FindModifier(SlangReflectionFunction* inFunc, SlangModifierID modifierID) { auto funcDeclRef = convert(inFunc); - auto varRefl = convert(funcDeclRef.getDecl()); + auto varRefl = convert(funcDeclRef.as()); if (!varRefl) return nullptr; return spReflectionVariable_FindModifier(varRefl, modifierID); @@ -2888,7 +2990,16 @@ SLANG_API SlangReflectionVariable* spReflectionFunction_GetParameter(SlangReflec { auto func = convert(inFunc); if (!func) return nullptr; - return convert(as(func.getDecl()->getParameters()[index])); + + auto astBuilder = getModule(func.getDecl())->getLinkage()->getASTBuilder(); + + return convert(getParameters(astBuilder, func)[index]); +} + +SLANG_API SlangReflectionGeneric* spReflectionFunction_GetGenericContainer(SlangReflectionFunction* func) +{ + auto declRef = convert(func); + return getInnermostGenericParent(declRef); } // Abstract decl reflection @@ -2960,20 +3071,31 @@ SLANG_API SlangReflectionVariable* spReflectionDecl_castToVariable(SlangReflecti Decl* slangDecl = (Decl*) decl; if (auto varDecl = as(slangDecl)) { - return (SlangReflectionVariable*) varDecl; + return convert(DeclRef(varDecl)); } // Improper cast return nullptr; +} + +SLANG_API SlangReflectionGeneric* spReflectionDecl_castToGeneric(SlangReflectionDecl* decl) +{ + Decl* slangDecl = (Decl*) decl; + if (auto genericInnerDecl = as(slangDecl)->inner) + { + return convertDeclToGeneric(genericInnerDecl); + } + // Improper cast + return nullptr; } -SLANG_API SlangReflectionType* spReflection_getTypeFromDecl(SlangSession* session, SlangReflectionDecl* decl) +SLANG_API SlangReflectionType* spReflection_getTypeFromDecl(SlangReflectionDecl* decl) { Decl* slangDecl = (Decl*)decl; - auto slangSession = asInternal(session); - ASTBuilder* builder = slangSession->getGlobalASTBuilder(); + ASTBuilder* builder = getModule(slangDecl)->getLinkage()->getASTBuilder(); + // TODO: create default substitutions if (auto type = DeclRefType::create(builder, slangDecl->getDefaultDeclRef())) { return convert(type); @@ -2983,6 +3105,178 @@ SLANG_API SlangReflectionType* spReflection_getTypeFromDecl(SlangSession* sessio return nullptr; } +SLANG_API SlangReflectionDecl* spReflectionDecl_getParent(SlangReflectionDecl* decl) +{ + Decl* slangDecl = (Decl*)decl; + if (auto parentDecl = slangDecl->parentDecl) + { + return (SlangReflectionDecl*)parentDecl; + } + + return nullptr; +} + +// Generic Reflection + +SLANG_API SlangReflectionDecl* spReflectionGeneric_asDecl(SlangReflectionGeneric* generic) +{ + return (SlangReflectionDecl*) convertGenericToDeclRef(generic).getDecl()->parentDecl; +} + +SLANG_API char const* spReflectionGeneric_GetName(SlangReflectionGeneric* generic) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + return getText(slangGeneric.getDecl()->getName()).getBuffer(); +} + +SLANG_API unsigned int spReflectionGeneric_GetTypeParameterCount(SlangReflectionGeneric* generic) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return 0; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + return (unsigned int) getMembersOfType(astBuilder, slangGeneric.getDecl()->parentDecl).getCount(); +} + +SLANG_API SlangReflectionVariable* spReflectionGeneric_GetTypeParameter(SlangReflectionGeneric* generic, unsigned index) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + auto paramDeclRef = getMembersOfType(astBuilder, slangGeneric.getDecl()->parentDecl)[index]; + + return convert(substituteDeclRef(SubstitutionSet(slangGeneric), astBuilder, paramDeclRef)); +} + +SLANG_API unsigned int spReflectionGeneric_GetValueParameterCount(SlangReflectionGeneric* generic) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return 0; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + return (unsigned int) getMembersOfType(astBuilder, slangGeneric.getDecl()->parentDecl).getCount(); +} + +SLANG_API SlangReflectionVariable* spReflectionGeneric_GetValueParameter(SlangReflectionGeneric* generic, unsigned index) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + auto paramDeclRef = getMembersOfType(astBuilder, slangGeneric.getDecl()->parentDecl)[index]; + + return convert(substituteDeclRef(SubstitutionSet(slangGeneric), astBuilder, paramDeclRef)); +} + +SLANG_API unsigned int spReflectionGeneric_GetTypeParameterConstraintCount(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return 0; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + if (auto typeParamDecl = as(convert(typeParam).getDecl())) + { + auto constraints = getCanonicalGenericConstraints( + astBuilder, + DeclRef(slangGeneric.getDecl()->parentDecl)); + return (unsigned int)(constraints[typeParamDecl]).getValue().getCount(); + } + + return 0; +} + +SLANG_API SlangReflectionType* spReflectionGeneric_GetTypeParameterConstraintType(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam, unsigned index) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + if (auto typeParamDecl = as(convert(typeParam).getDecl())) + { + auto constraints = getCanonicalGenericConstraints( + astBuilder, + DeclRef(slangGeneric.getDecl()->parentDecl)); + if (auto constraint = (constraints[typeParamDecl]).getValue()[index]) + { + return convert(substituteType(SubstitutionSet(slangGeneric), astBuilder, constraint)); + } + } + + return nullptr; +} + +SLANG_API SlangDeclKind spReflectionGeneric_GetInnerKind(SlangReflectionGeneric* generic) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION; + + return spReflectionDecl_getKind((SlangReflectionDecl*)slangGeneric.getDecl()); +} + +SLANG_API SlangReflectionDecl* spReflectionGeneric_GetInnerDecl(SlangReflectionGeneric* generic) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + + return (SlangReflectionDecl*)slangGeneric.getDecl(); +} + +SLANG_API SlangReflectionGeneric* spReflectionGeneric_GetOuterGenericContainer(SlangReflectionGeneric* generic) +{ + auto declRef = convertGenericToDeclRef(generic); + + auto astBuilder = getModule(declRef.getDecl())->getLinkage()->getASTBuilder(); + + return getInnermostGenericParent( + substituteDeclRef( + SubstitutionSet(declRef), + astBuilder, + createDefaultSubstitutionsIfNeeded(astBuilder, nullptr, DeclRef(declRef.getDecl()->parentDecl)))); +} + +SLANG_API SlangReflectionType* spReflectionGeneric_GetConcreteType(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return nullptr; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + auto genericType = DeclRefType::create(astBuilder, convert(typeParam)); + + auto substType = substituteType(SubstitutionSet(slangGeneric), astBuilder, genericType); + + if (genericType != substType) + { + return convert(substType); + } + + return nullptr; +} + +SLANG_API int64_t spReflectionGeneric_GetConcreteIntVal(SlangReflectionGeneric* generic, SlangReflectionVariable* valueParam) +{ + auto slangGeneric = convertGenericToDeclRef(generic); + if (!slangGeneric) return 0; + auto astBuilder = getModule(slangGeneric.getDecl())->getLinkage()->getASTBuilder(); + + auto valueParamDeclRef = convert(valueParam); + + Val* valResult = astBuilder->getOrCreate( + valueParamDeclRef.substitute(astBuilder, as(valueParamDeclRef.getDecl())->getType()), + valueParamDeclRef); + valResult = valResult->substitute(astBuilder, SubstitutionSet(slangGeneric)); + + auto intVal = as(valResult); + if (intVal) + { + return intVal->getValue(); + } + + return 0; +} + + // Shader Parameter Reflection SLANG_API unsigned spReflectionParameter_GetBindingIndex(SlangReflectionParameter* inVarLayout) @@ -3046,7 +3340,7 @@ SLANG_API SlangReflectionFunction* spReflectionEntryPoint_GetFunction(SlangRefle auto entryPointLayout = convert(inEntryPoint); if (entryPointLayout) { - return convert(entryPointLayout->entryPoint); + return convert(entryPointLayout->entryPoint.as()); } return nullptr; } -- cgit v1.2.3