summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorSai Praveen Bangaru <31557731+saipraveenb25@users.noreply.github.com>2024-07-18 13:11:19 -0400
committerGitHub <noreply@github.com>2024-07-18 13:11:19 -0400
commit0d06ebcefb36a19710d87832fc1ea027e21281af (patch)
tree05ac5af6fa26a658348335eac3d63199b6949507 /include
parent89e836d42822e69dcaa4eb0a366d8c66e5aaa7e4 (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.h160
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()