diff options
| author | Sai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com> | 2024-07-18 13:11:19 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-18 13:11:19 -0400 |
| commit | 0d06ebcefb36a19710d87832fc1ea027e21281af (patch) | |
| tree | 05ac5af6fa26a658348335eac3d63199b6949507 /include | |
| parent | 89e836d42822e69dcaa4eb0a366d8c66e5aaa7e4 (diff) | |
Initial implementation for decl-tree reflection API (#4666)
* Initial implementation for decl-tree reflection API
This patch adds Slang API methods for walking all the declarations in the AST.
We expose this functionality through an abstract `DeclReflection` class that can be a type, function or a variable declaration.
We also provide ways to cast the decl to a `FunctionReflection`, `TypeReflection` or `VariableReflection` and traverse through the child nodes (for instance, a struct type will have component variable declarations)
This patch also adds `ISlangInternal` as an internal COM interface to allow us to cast IGlobalSession to the internal Session pointer while bypassing any wrappers (such as the capture interface)
* Update slang.h
* Remove `ISlangInternal` (its causing a diamond pattern w.r.t `ISlangUnknown`) and use `ComPtr` for proper ref management.
* Update unit-test-decl-tree-reflection.cpp
* Change `FunctionDeclBase` to use `DeclRef` instead of directly using the decl.
* Update slang-reflection-api.cpp
Diffstat (limited to 'include')
| -rw-r--r-- | include/slang.h | 160 |
1 files changed, 156 insertions, 4 deletions
diff --git a/include/slang.h b/include/slang.h index 2f8f8d15d..86ca4649b 100644 --- a/include/slang.h +++ b/include/slang.h @@ -2107,6 +2107,7 @@ extern "C" typedef struct SlangEntryPoint SlangEntryPoint; typedef struct SlangEntryPointLayout SlangEntryPointLayout; + typedef struct SlangReflectionDecl SlangReflectionDecl; typedef struct SlangReflectionModifier SlangReflectionModifier; typedef struct SlangReflectionType SlangReflectionType; typedef struct SlangReflectionTypeLayout SlangReflectionTypeLayout; @@ -2174,6 +2175,18 @@ extern "C" SLANG_SCALAR_TYPE_UINTPTR }; + // abstract decl reflection + typedef unsigned int SlangDeclKindIntegral; + enum SlangDeclKind : SlangDeclKindIntegral + { + SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION, + SLANG_DECL_KIND_STRUCT, + SLANG_DECL_KIND_FUNC, + SLANG_DECL_KIND_MODULE, + SLANG_DECL_KIND_GENERIC, + SLANG_DECL_KIND_VARIABLE + }; + #ifndef SLANG_RESOURCE_SHAPE # define SLANG_RESOURCE_SHAPE typedef unsigned int SlangResourceShapeIntegral; @@ -2394,6 +2407,7 @@ extern "C" SLANG_MODIFIER_EXPORT, SLANG_MODIFIER_EXTERN, SLANG_MODIFIER_DIFFERENTIABLE, + SLANG_MODIFIER_MUTATING }; // User Attribute @@ -2528,6 +2542,7 @@ extern "C" SLANG_API unsigned int spReflectionVariable_GetUserAttributeCount(SlangReflectionVariable* var); SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute(SlangReflectionVariable* var, unsigned int index); SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName(SlangReflectionVariable* var, SlangSession * globalSession, char const* name); + SLANG_API bool spReflectionVariable_HasDefaultValue(SlangReflectionVariable* inVar); // Variable Layout Reflection @@ -2544,7 +2559,9 @@ extern "C" // Function Reflection + SLANG_API SlangReflectionDecl* spReflectionFunction_asDecl(SlangReflectionFunction* func); SLANG_API char const* spReflectionFunction_GetName(SlangReflectionFunction* func); + SLANG_API SlangReflectionModifier* spReflectionFunction_FindModifier(SlangReflectionFunction* var, SlangModifierID modifierID); SLANG_API unsigned int spReflectionFunction_GetUserAttributeCount(SlangReflectionFunction* func); SLANG_API SlangReflectionUserAttribute* spReflectionFunction_GetUserAttribute(SlangReflectionFunction* func, unsigned int index); SLANG_API SlangReflectionUserAttribute* spReflectionFunction_FindUserAttributeByName(SlangReflectionFunction* func, SlangSession* globalSession, char const* name); @@ -2552,6 +2569,16 @@ extern "C" SLANG_API SlangReflectionVariable* spReflectionFunction_GetParameter(SlangReflectionFunction* func, unsigned index); SLANG_API SlangReflectionType* spReflectionFunction_GetResultType(SlangReflectionFunction* func); + // Abstract Decl Reflection + + SLANG_API unsigned int spReflectionDecl_getChildrenCount(SlangReflectionDecl* parentDecl); + SLANG_API SlangReflectionDecl* spReflectionDecl_getChild(SlangReflectionDecl* parentDecl, unsigned int index); + SLANG_API SlangDeclKind spReflectionDecl_getKind(SlangReflectionDecl* decl); + SLANG_API SlangReflectionFunction* spReflectionDecl_castToFunction(SlangReflectionDecl* decl); + SLANG_API SlangReflectionVariable* spReflectionDecl_castToVariable(SlangReflectionDecl* decl); + SLANG_API SlangReflectionType* spReflection_getTypeFromDecl(SlangSession* session, SlangReflectionDecl* decl); + + /** Get the stage that a variable belongs to (if any). A variable "belongs" to a specific stage when it is a varying input/output @@ -2693,6 +2720,7 @@ SLANG_API slang::ISession* spReflection_GetSession(SlangReflection* reflection); namespace slang { struct BufferReflection; + struct DeclReflection; struct TypeLayoutReflection; struct TypeReflection; struct VariableLayoutReflection; @@ -3293,6 +3321,7 @@ namespace slang Export = SLANG_MODIFIER_EXPORT, Extern = SLANG_MODIFIER_EXTERN, Differentiable = SLANG_MODIFIER_DIFFERENTIABLE, + Mutating = SLANG_MODIFIER_MUTATING }; }; @@ -3325,6 +3354,11 @@ namespace slang { return (UserAttribute*)spReflectionVariable_FindUserAttributeByName((SlangReflectionVariable*)this, globalSession, name); } + + bool hasDefaultValue() + { + return spReflectionVariable_HasDefaultValue((SlangReflectionVariable*)this); + } }; struct VariableLayoutReflection @@ -3435,20 +3469,20 @@ namespace slang unsigned int getUserAttributeCount() { - return spReflectionVariable_GetUserAttributeCount((SlangReflectionVariable*)this); + return spReflectionFunction_GetUserAttributeCount((SlangReflectionFunction*)this); } UserAttribute* getUserAttributeByIndex(unsigned int index) { - return (UserAttribute*)spReflectionVariable_GetUserAttribute((SlangReflectionVariable*)this, index); + return (UserAttribute*)spReflectionFunction_GetUserAttribute((SlangReflectionFunction*)this, index); } UserAttribute* findUserAttributeByName(SlangSession* globalSession, char const* name) { - return (UserAttribute*)spReflectionVariable_FindUserAttributeByName((SlangReflectionVariable*)this, globalSession, name); + return (UserAttribute*)spReflectionFunction_FindUserAttributeByName((SlangReflectionFunction*)this, globalSession, name); } Modifier* findModifier(Modifier::ID id) { - return (Modifier*)spReflectionVariable_FindModifier((SlangReflectionVariable*)this, (SlangModifierID)id); + return (Modifier*)spReflectionFunction_FindModifier((SlangReflectionFunction*)this, (SlangModifierID)id); } }; @@ -3672,6 +3706,122 @@ namespace slang } }; + + struct DeclReflection + { + enum class Kind + { + Unsupported = SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION, + Struct = SLANG_DECL_KIND_STRUCT, + Func = SLANG_DECL_KIND_FUNC, + Module = SLANG_DECL_KIND_MODULE, + Generic = SLANG_DECL_KIND_GENERIC, + Variable = SLANG_DECL_KIND_VARIABLE, + }; + + Kind getKind() + { + return (Kind)spReflectionDecl_getKind((SlangReflectionDecl*)this); + } + + unsigned int getChildrenCount() + { + return spReflectionDecl_getChildrenCount((SlangReflectionDecl*)this); + } + + DeclReflection* getChild(unsigned int index) + { + return (DeclReflection*)spReflectionDecl_getChild((SlangReflectionDecl*)this, index); + } + + TypeReflection* getType(SlangSession* session) + { + return (TypeReflection*)spReflection_getTypeFromDecl(session, (SlangReflectionDecl*)this); + } + + VariableReflection* asVariable() + { + return (VariableReflection*)spReflectionDecl_castToVariable((SlangReflectionDecl*)this); + } + + FunctionReflection* asFunction() + { + return (FunctionReflection*)spReflectionDecl_castToFunction((SlangReflectionDecl*)this); + } + + template <Kind K> + struct FilteredList + { + unsigned int count; + DeclReflection* parent; + + struct FilteredIterator + { + DeclReflection* parent; + unsigned int count; + unsigned int index; + + DeclReflection* operator*() { return parent->getChild(index); } + void operator++() + { + index++; + while (index < count && !(parent->getChild(index)->getKind() == K)) + { + index++; + } + } + bool operator!=(FilteredIterator const& other) { return index != other.index; } + }; + + // begin/end for range-based for that checks the kind + FilteredIterator begin() + { + // Find the first child of the right kind + unsigned int index = 0; + while (index < count && !(parent->getChild(index)->getKind() == K)) + { + index++; + } + return FilteredIterator{parent, count, index}; + } + + FilteredIterator end() { return FilteredIterator{parent, count, count}; } + }; + + template <Kind K> + FilteredList<K> getChildrenOfKind() + { + return FilteredList<K>{ getChildrenCount(), (DeclReflection*)this }; + } + + struct IteratedList + { + unsigned int count; + DeclReflection* parent; + + struct Iterator + { + DeclReflection* parent; + unsigned int count; + unsigned int index; + + DeclReflection* operator*() { return parent->getChild(index); } + void operator++() { index++; } + bool operator!=(Iterator const& other) { return index != other.index; } + }; + + // begin/end for range-based for that checks the kind + IteratedList::Iterator begin() { return IteratedList::Iterator{ parent, count, 0 }; } + IteratedList::Iterator end() { return IteratedList::Iterator{ parent, count, count }; } + }; + + IteratedList getChildren() + { + return IteratedList{ getChildrenCount(), (DeclReflection*)this }; + } + + }; + typedef uint32_t CompileStdLibFlags; struct CompileStdLibFlag { @@ -5132,6 +5282,8 @@ namespace slang /// Get the path to a file this module depends on. virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath( SlangInt32 index) = 0; + + virtual SLANG_NO_THROW DeclReflection* SLANG_MCALL getModuleReflection() = 0; }; #define SLANG_UUID_IModule IModule::getTypeGuid() |
