diff --git a/Src/ILGPU/IR/Types/ArrayType.cs b/Src/ILGPU/IR/Types/ArrayType.cs
index f78d1eb40..56a6133bd 100644
--- a/Src/ILGPU/IR/Types/ArrayType.cs
+++ b/Src/ILGPU/IR/Types/ArrayType.cs
@@ -17,6 +17,7 @@ namespace ILGPU.IR.Types
///
/// Represents the type of a generic array that lives in the local address space.
///
+ [TypeKind(TypeKind.Array)]
public sealed class ArrayType : TypeNode
{
#region Instance
diff --git a/Src/ILGPU/IR/Types/HandleType.cs b/Src/ILGPU/IR/Types/HandleType.cs
index 696c11c98..cf21b6fb2 100644
--- a/Src/ILGPU/IR/Types/HandleType.cs
+++ b/Src/ILGPU/IR/Types/HandleType.cs
@@ -17,6 +17,7 @@ namespace ILGPU.IR.Types
///
/// Represents a .Net runtime-specific handle type.
///
+ [TypeKind(TypeKind.Handle)]
public sealed class HandleType : TypeNode
{
#region Instance
diff --git a/Src/ILGPU/IR/Types/PaddingType.cs b/Src/ILGPU/IR/Types/PaddingType.cs
index 24f273f75..204894be4 100644
--- a/Src/ILGPU/IR/Types/PaddingType.cs
+++ b/Src/ILGPU/IR/Types/PaddingType.cs
@@ -17,6 +17,7 @@ namespace ILGPU.IR.Types
///
/// Represents a padding type.
///
+ [TypeKind(TypeKind.Padding)]
public sealed class PaddingType : TypeNode
{
#region Instance
diff --git a/Src/ILGPU/IR/Types/PointerTypes.cs b/Src/ILGPU/IR/Types/PointerTypes.cs
index 582144e38..3f93482e1 100644
--- a/Src/ILGPU/IR/Types/PointerTypes.cs
+++ b/Src/ILGPU/IR/Types/PointerTypes.cs
@@ -161,6 +161,7 @@ public override string ToString() =>
///
/// Represents the type of a generic pointer.
///
+ [TypeKind(TypeKind.Pointer)]
public sealed class PointerType : AddressSpaceType
{
#region Instance
@@ -245,6 +246,7 @@ public override bool Equals(object? obj) =>
///
/// Represents the type of a generic view.
///
+ [TypeKind(TypeKind.View)]
public sealed class ViewType : AddressSpaceType
{
#region Instance
diff --git a/Src/ILGPU/IR/Types/PrimitiveTypes.cs b/Src/ILGPU/IR/Types/PrimitiveTypes.cs
index 34aecce64..b9b3feef1 100644
--- a/Src/ILGPU/IR/Types/PrimitiveTypes.cs
+++ b/Src/ILGPU/IR/Types/PrimitiveTypes.cs
@@ -18,6 +18,7 @@ namespace ILGPU.IR.Types
///
/// Represents a primitive type.
///
+ [TypeKind(TypeKind.Primitive)]
public sealed class PrimitiveType : TypeNode
{
#region Static
@@ -152,6 +153,7 @@ obj is PrimitiveType primitiveType &&
///
/// Represents a string type.
///
+ [TypeKind(TypeKind.String)]
public sealed class StringType : TypeNode
{
#region Instance
diff --git a/Src/ILGPU/IR/Types/StructureType.cs b/Src/ILGPU/IR/Types/StructureType.cs
index fd0bdebdf..8f0fde97a 100644
--- a/Src/ILGPU/IR/Types/StructureType.cs
+++ b/Src/ILGPU/IR/Types/StructureType.cs
@@ -26,6 +26,7 @@ namespace ILGPU.IR.Types
///
/// Represents a structure type.
///
+ [TypeKind(TypeKind.Structure)]
public sealed class StructureType : ObjectType, IEnumerable<(TypeNode, FieldAccess)>
{
#region Nested Types
diff --git a/Src/ILGPU/IR/Types/TypeKind.cs b/Src/ILGPU/IR/Types/TypeKind.cs
index 60a76b148..4613515ca 100644
--- a/Src/ILGPU/IR/Types/TypeKind.cs
+++ b/Src/ILGPU/IR/Types/TypeKind.cs
@@ -3,12 +3,16 @@
// Copyright (c) 2024 ILGPU Project
// www.ilgpu.net
//
-// File: TypeNodeKind.cs
+// File: TypeKind.cs
//
// This file is part of ILGPU and is distributed under the University of Illinois Open
// Source License. See LICENSE.txt for details.
// ---------------------------------------------------------------------------------------
+using ILGPU.Util;
+using System;
+using System.Reflection;
+
namespace ILGPU.IR.Types
{
///
@@ -65,5 +69,58 @@ public enum TypeKind
/// See
///
Handle,
+
+ ///
+ /// Represents the number of distinct type kinds described by this enumeration
+ ///
+ MaxValue,
+ }
+
+ ///
+ /// Marks value classes with specific type kinds.
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ internal sealed class TypeKindAttribute : Attribute
+ {
+ ///
+ /// Constructs a new type kind attribute.
+ ///
+ /// The type kind.
+ public TypeKindAttribute(TypeKind kind)
+ {
+ Kind = kind;
+ }
+
+ ///
+ /// Returns the type kind.
+ ///
+ public TypeKind Kind { get; }
+ }
+
+ ///
+ /// Utility methods for enumeration values.
+ ///
+ public static class TypeKinds
+ {
+ ///
+ /// The number of different value kinds.
+ ///
+ public const int NumTypeKinds = (int)TypeKind.MaxValue;
+
+ ///
+ /// Gets the value kind of the value type specified.
+ ///
+ /// The compile-time type.
+ /// The determined type kind.
+ public static TypeKind GetTypeKind()
+ where TType : TypeNode =>
+ typeof(TType).GetCustomAttribute().AsNotNull().Kind;
+
+ ///
+ /// Gets the type kind of the type specified.
+ ///
+ /// The determined type kind.
+ public static TypeKind? GetTypeKind(Type type) =>
+ type.GetCustomAttribute()?.Kind;
}
}
diff --git a/Src/ILGPU/IR/Types/VoidType.cs b/Src/ILGPU/IR/Types/VoidType.cs
index 935e90c29..cb6d78206 100644
--- a/Src/ILGPU/IR/Types/VoidType.cs
+++ b/Src/ILGPU/IR/Types/VoidType.cs
@@ -17,6 +17,7 @@ namespace ILGPU.IR.Types
///
/// Represents a void type.
///
+ [TypeKind(TypeKind.Void)]
public sealed class VoidType : TypeNode
{
#region Instance