diff --git a/Samples/AdjustableSharedMemory/Program.cs b/Samples/AdjustableSharedMemory/Program.cs
index 5e669ccf4..f070ea5e3 100644
--- a/Samples/AdjustableSharedMemory/Program.cs
+++ b/Samples/AdjustableSharedMemory/Program.cs
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU Samples
-// Copyright (c) 2021 ILGPU Project
+// Copyright (c) 2021-2024 ILGPU Project
// www.ilgpu.net
//
// File: Program.cs
@@ -31,7 +31,7 @@ interface ISharedAllocationSize
struct SharedArray32 : ISharedAllocationSize
{
///
- /// Returns a
+ /// Returns a
///
public int ArraySize => 32;
}
@@ -49,7 +49,7 @@ struct SharedArray64 : ISharedAllocationSize
/// Implicit shared-memory parameter that is handled by the runtime.
static void SharedMemoryKernel(
ArrayView outputView) // A view to a chunk of memory (1D in this case)
- where TSharedAllocationSize : struct, ISharedAllocationSize
+ where TSharedAllocationSize : unmanaged, ISharedAllocationSize
{
// Compute the global 1D index for accessing the data view
var globalIndex = Grid.GlobalIndex.X;
@@ -66,7 +66,7 @@ static void SharedMemoryKernel(
}
static void ExecuteSample(Context context)
- where TSharedAllocationSize : struct, ISharedAllocationSize
+ where TSharedAllocationSize : unmanaged, ISharedAllocationSize
{
// For each available device...
foreach (var device in context)
diff --git a/Samples/GenericKernel/Program.cs b/Samples/GenericKernel/Program.cs
index 9e66aed14..f3fe7313a 100644
--- a/Samples/GenericKernel/Program.cs
+++ b/Samples/GenericKernel/Program.cs
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU Samples
-// Copyright (c) 2021 ILGPU Project
+// Copyright (c) 2021-2024 ILGPU Project
// www.ilgpu.net
//
// File: Program.cs
@@ -72,7 +72,7 @@ static void Kernel(
ArrayView data,
int value,
TKernelFunction function)
- where TKernelFunction : struct, IKernelFunction
+ where TKernelFunction : unmanaged, IKernelFunction
where T : unmanaged
{
// Invoke the custom "lambda function"
diff --git a/Samples/ILGPU.Samples.sln b/Samples/ILGPU.Samples.sln
index ce9098eb9..ba07fe3fd 100644
--- a/Samples/ILGPU.Samples.sln
+++ b/Samples/ILGPU.Samples.sln
@@ -135,6 +135,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILGPU.Analyzers", "..\Src\I
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InterleaveFields", "InterleaveFields\InterleaveFields.csproj", "{1E6D0BC6-CFA1-4F52-9EB9-CAA62DD2F33A}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ILGPU.Analyzers", "ILGPU.Analyzers", "{6D111E09-49A1-492E-B4CE-E18CE27B56A8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ManagedTypeAnalyzer", "ManagedTypeAnalyzer\ManagedTypeAnalyzer.csproj", "{6176F0D0-4A34-42DB-BDFB-2D8ED80868C3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -381,6 +385,10 @@ Global
{1E6D0BC6-CFA1-4F52-9EB9-CAA62DD2F33A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E6D0BC6-CFA1-4F52-9EB9-CAA62DD2F33A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E6D0BC6-CFA1-4F52-9EB9-CAA62DD2F33A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6176F0D0-4A34-42DB-BDFB-2D8ED80868C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6176F0D0-4A34-42DB-BDFB-2D8ED80868C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6176F0D0-4A34-42DB-BDFB-2D8ED80868C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6176F0D0-4A34-42DB-BDFB-2D8ED80868C3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -449,6 +457,7 @@ Global
{70B69CE3-24A9-463C-B14C-E2934988BBEE} = {25BA2234-5778-40BC-9386-9CE87AB87D1F}
{1C5E9E39-3C14-4B52-8D97-04555D5F6331} = {03FCC663-945D-4982-90D8-B14BE52D8FCD}
{1E6D0BC6-CFA1-4F52-9EB9-CAA62DD2F33A} = {C1D99632-ED4A-4B08-A14D-4C8DB375934F}
+ {6176F0D0-4A34-42DB-BDFB-2D8ED80868C3} = {6D111E09-49A1-492E-B4CE-E18CE27B56A8}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {30E502BD-3826-417F-888F-1CE19CF5C6DA}
diff --git a/Samples/ManagedTypeAnalyzer/ManagedTypeAnalyzer.csproj b/Samples/ManagedTypeAnalyzer/ManagedTypeAnalyzer.csproj
new file mode 100644
index 000000000..4e6d0c8c8
--- /dev/null
+++ b/Samples/ManagedTypeAnalyzer/ManagedTypeAnalyzer.csproj
@@ -0,0 +1,17 @@
+
+
+ Exe
+ $(LibrarySamplesTargetFrameworks)
+ enable
+ enable
+ ManagedTypeAnalyzer
+
+
+
+
+
+
+
+
diff --git a/Samples/ManagedTypeAnalyzer/Program.cs b/Samples/ManagedTypeAnalyzer/Program.cs
new file mode 100644
index 000000000..b717799ba
--- /dev/null
+++ b/Samples/ManagedTypeAnalyzer/Program.cs
@@ -0,0 +1,88 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU Samples
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Program.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;
+using ILGPU.Runtime;
+using System.Diagnostics.CodeAnalysis;
+
+namespace ManagedTypeAnalyzer;
+
+// Disable warnings for build
+[SuppressMessage("Usage", "ILA003:Managed type in kernel")]
+[SuppressMessage("Usage", "ILA004:Array of managed types in kernel")]
+class Program
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ struct ValueType
+ {
+ public int Hello;
+
+ public ValueType()
+ {
+ Hello = 42;
+ }
+ }
+
+ static int AnotherFunction()
+ {
+ return new RefType().Hello;
+ }
+
+ static void Kernel(Index1D index, ArrayView input, ArrayView output)
+ {
+ // This is disallowed, since MyRefType is a reference type
+ var refType = new RefType();
+ output[index] = input[index] + refType.Hello;
+
+ // Allocating arrays of unmanaged types is fine
+ ValueType[] array =
+ {
+ new ValueType()
+ };
+
+ int[] ints =
+ {
+ 0, 1, 2
+ };
+
+ // But arrays of reference types are still disallowed
+ RefType[] other =
+ {
+ new RefType(),
+ };
+
+ // Any functions that may be called are also analyzed
+ int result = AnotherFunction();
+ }
+
+ static void Main(string[] args)
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+ using var output = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator
+ .LoadAutoGroupedStreamKernel, ArrayView>(
+ Kernel);
+
+ kernel(input.IntExtent, input.View, output.View);
+
+ accelerator.Synchronize();
+ }
+}
diff --git a/Samples/StaticAbstractInterfaceMembers/Program.cs b/Samples/StaticAbstractInterfaceMembers/Program.cs
index f11a3e8a8..6980eafb7 100644
--- a/Samples/StaticAbstractInterfaceMembers/Program.cs
+++ b/Samples/StaticAbstractInterfaceMembers/Program.cs
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU Samples
-// Copyright (c) 2023 ILGPU Project
+// Copyright (c) 2023-2024 ILGPU Project
// www.ilgpu.net
//
// File: Program.cs
@@ -66,13 +66,13 @@ public interface ICalculatorOperation
{
T Calculate(T left, T right);
}
-
+
// Interface must be implemented by a 'struct'.
public struct AdditionOp : ICalculatorOperation
{
public int Calculate(int left, int right) => left + right;
}
-
+
// Interface must be implemented by a 'struct'.
public struct MultiplyOp : ICalculatorOperation
{
@@ -84,7 +84,7 @@ public static void CalculatorKernel(
ArrayView1D input,
ArrayView1D output)
where T : unmanaged
- where TOp : struct, ICalculatorOperation
+ where TOp : unmanaged, ICalculatorOperation
{
// Creates a new instance of the struct, and calls the method.
output[index] = default(TOp).Calculate(input[index], input[index]);
@@ -98,7 +98,7 @@ public static void UsingAbstractFunction(Accelerator accelerator)
where TOp : ICalculatorOperation
#else
where T : unmanaged
- where TOp : struct, ICalculatorOperation
+ where TOp : unmanaged, ICalculatorOperation
#endif
{
var values =
diff --git a/Src/ILGPU.Analyzers.Tests/Generic/DiagnosticAnalyzerVerifier.cs b/Src/ILGPU.Analyzers.Tests/Generic/DiagnosticAnalyzerVerifier.cs
new file mode 100644
index 000000000..99da0ff8d
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Generic/DiagnosticAnalyzerVerifier.cs
@@ -0,0 +1,68 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: DiagnosticAnalyzerVerifier.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using System;
+using System.Collections.Immutable;
+using System.IO;
+using System.Threading.Tasks;
+using ILGPU.CodeGeneration;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using VerifyTests;
+using VerifyXunit;
+
+namespace ILGPU.Analyzers.Tests.Generic;
+
+///
+/// Verifies the output of running TDiagnosticAnalyzer on C# source.
+///
+/// The diagnostic analyzer to run.
+public static class DiagnosticAnalyzerVerifier
+ where TDiagnosticAnalyzer : DiagnosticAnalyzer, new()
+{
+ ///
+ /// Verifies the output of running TDiagnosticAnalyzer on source using
+ /// snapshots.
+ ///
+ /// The source to run the analyzer on.
+ ///
+ /// Optional action to configure verification settings.
+ ///
+ public static async Task Verify(string source,
+ Action configure = null)
+ {
+ var ilgpuAssemblies =
+ new[]
+ {
+ typeof(InterleaveFieldsAttribute).Assembly,
+ typeof(TDiagnosticAnalyzer).Assembly
+ };
+
+ var compilation =
+ SourceCompiler.CreateCompilationWithAssemblies("Tests", source,
+ ilgpuAssemblies);
+
+ var array = ImmutableArray.Create(new TDiagnosticAnalyzer());
+ var options = new AnalyzerOptions(ImmutableArray.Empty);
+ var analyzerCompilation =
+ new CompilationWithAnalyzers(compilation, array, options);
+
+ var diagnostics = await analyzerCompilation.GetAnalyzerDiagnosticsAsync();
+
+ var settings = new VerifySettings();
+ settings.UseDirectory(Path.Combine("..", "Snapshots"));
+
+ if (configure is not null)
+ configure(settings);
+
+ await Verifier.Verify(diagnostics, settings);
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Generic/IncrementalGeneratorVerifier.cs b/Src/ILGPU.Analyzers.Tests/Generic/IncrementalGeneratorVerifier.cs
index 9b4771ee0..88bec1a6c 100644
--- a/Src/ILGPU.Analyzers.Tests/Generic/IncrementalGeneratorVerifier.cs
+++ b/Src/ILGPU.Analyzers.Tests/Generic/IncrementalGeneratorVerifier.cs
@@ -12,46 +12,40 @@
using ILGPU.CodeGeneration;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
-using System;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
using VerifyTests;
using VerifyXunit;
-namespace ILGPU.Analyzers.Tests
+namespace ILGPU.Analyzers.Tests.Generic
{
+ ///
+ /// Verifies the output source from the source generator TIncrementalGenerator
+ /// using snapshots.
+ ///
+ ///
+ /// The generator to run on source text.
+ ///
public static class IncrementalGeneratorVerifier
where TIncrementalGenerator : IIncrementalGenerator, new()
{
+ ///
+ /// Verifies the C# source generated by TIncrementalGenerator.
+ ///
+ /// The source text to run the generator on.
+ /// A task that runs the generator and verifies the output.
public static Task Verify(string source)
{
- // Parse syntax tree.
- var syntaxTree = CSharpSyntaxTree.ParseText(source);
-
- // Add system references.
- var trustedAssembliesPaths =
- (string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES");
- var systemReferences =
- trustedAssembliesPaths
- .Split(Path.PathSeparator)
- .Select(x => MetadataReference.CreateFromFile(x))
- .ToArray();
-
- var ilgpuReferences =
+ var ilgpuAssemblies =
new[]
{
- typeof(InterleaveFieldsAttribute),
- typeof(TIncrementalGenerator)
- }
- .Select(x => MetadataReference.CreateFromFile(x.Assembly.Location))
- .ToArray();
+ typeof(InterleaveFieldsAttribute).Assembly,
+ typeof(TIncrementalGenerator).Assembly
+ };
- // Create a roslyn compilation for the syntax tree.
- var compilation = CSharpCompilation.Create(
- "Tests",
- new[] { syntaxTree },
- references: systemReferences.Concat(ilgpuReferences));
+ var compilation =
+ SourceCompiler.CreateCompilationWithAssemblies("Tests", source,
+ ilgpuAssemblies);
// Create an instance of the incremental source generator.
var generator = new TIncrementalGenerator();
@@ -65,4 +59,4 @@ public static Task Verify(string source)
return Verifier.Verify(driver, settings);
}
}
-}
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Generic/SourceCompiler.cs b/Src/ILGPU.Analyzers.Tests/Generic/SourceCompiler.cs
new file mode 100644
index 000000000..816dff341
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Generic/SourceCompiler.cs
@@ -0,0 +1,66 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: SourceCompiler.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace ILGPU.Analyzers.Tests.Generic;
+
+///
+/// Contains utility functions for compiling C# source files for analyzer testing.
+///
+public static class SourceCompiler
+{
+ ///
+ /// Compiles the source text source into an assembly with the name
+ /// assemblyName and includes the given additionalAssemblies.
+ ///
+ /// The name of the output assembly.
+ /// The source text to compile.
+ ///
+ /// The additional assembly references to include in the compilation.
+ ///
+ /// The resulting compilation.
+ public static CSharpCompilation CreateCompilationWithAssemblies(
+ string assemblyName,
+ string source,
+ Assembly[] additionalAssemblies)
+ {
+ // Parse syntax tree.
+ var syntaxTree = CSharpSyntaxTree.ParseText(source);
+
+ // Add system references.
+ var trustedAssembliesPaths =
+ (string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES");
+ var systemReferences =
+ trustedAssembliesPaths!
+ .Split(Path.PathSeparator)
+ .Select(x => MetadataReference.CreateFromFile(x))
+ .ToArray();
+
+ var additionalReferences =
+ additionalAssemblies
+ .Select(x => MetadataReference.CreateFromFile(x.Location))
+ .ToArray();
+
+ // Create a roslyn compilation for the syntax tree.
+ var compilation = CSharpCompilation.Create(
+ assemblyName,
+ new[] { syntaxTree },
+ references: systemReferences.Concat(additionalReferences));
+
+ return compilation;
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/ILGPU.Analyzers.Tests.csproj b/Src/ILGPU.Analyzers.Tests/ILGPU.Analyzers.Tests.csproj
index 9971c843c..69479bfac 100644
--- a/Src/ILGPU.Analyzers.Tests/ILGPU.Analyzers.Tests.csproj
+++ b/Src/ILGPU.Analyzers.Tests/ILGPU.Analyzers.Tests.csproj
@@ -23,8 +23,16 @@
+
+
+
+
+ Always
+
+
+
diff --git a/Src/ILGPU.Analyzers.Tests/InterleaveFields.cs b/Src/ILGPU.Analyzers.Tests/InterleaveFields.cs
index 5cc1b135a..36d9a3bda 100644
--- a/Src/ILGPU.Analyzers.Tests/InterleaveFields.cs
+++ b/Src/ILGPU.Analyzers.Tests/InterleaveFields.cs
@@ -10,10 +10,9 @@
// ---------------------------------------------------------------------------------------
using System.Threading.Tasks;
-using VerifyXunit;
using Xunit;
using VerifyCS =
- ILGPU.Analyzers.Tests.IncrementalGeneratorVerifier<
+ ILGPU.Analyzers.Tests.Generic.IncrementalGeneratorVerifier<
ILGPU.Analyzers.InterleaveFieldsGenerator>;
namespace ILGPU.Analyzers.Tests
diff --git a/Src/ILGPU.Analyzers.Tests/ManagedTypeAnalyzer.cs b/Src/ILGPU.Analyzers.Tests/ManagedTypeAnalyzer.cs
new file mode 100644
index 000000000..4714b945c
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/ManagedTypeAnalyzer.cs
@@ -0,0 +1,41 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: ManagedTypeAnalyzer.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using System.IO;
+using System.Threading.Tasks;
+using Xunit;
+using VerifyCS =
+ ILGPU.Analyzers.Tests.Generic.DiagnosticAnalyzerVerifier<
+ ILGPU.Analyzers.ManagedTypeAnalyzer>;
+
+namespace ILGPU.Analyzers.Tests;
+
+public class ManagedTypeAnalyzer
+{
+ [Theory]
+ [InlineData("Simple")]
+ [InlineData("Complex")]
+ [InlineData("Arrays")]
+ [InlineData("Functions")]
+ [InlineData("PartialMethods")]
+ [InlineData("Constructors")]
+ [InlineData("LoadDiscovery")]
+ [InlineData("ILGPUTypesIntrinsics")]
+ public async Task FileTests(string file)
+ {
+ // In build, we copy all programs to output directory.
+ // See ILGPU.Analyzers.Tests.csproj
+ var code = await File.ReadAllTextAsync(
+ $"Programs/ManagedType/{file}.cs"
+ );
+ await VerifyCS.Verify(code, settings => settings.UseParameters(file));
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Arrays.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Arrays.cs
new file mode 100644
index 000000000..26618b9ba
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Arrays.cs
@@ -0,0 +1,56 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Arrays.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class Arrays
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ struct ValueType
+ {
+ public int Hello;
+
+ public ValueType()
+ {
+ Hello = 42;
+ }
+ }
+
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ ValueType[] array = [new ValueType()];
+ int[] ints = [0, 1, 2];
+
+ RefType[] refs = [new RefType()];
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Complex.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Complex.cs
new file mode 100644
index 000000000..d0193d2d5
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Complex.cs
@@ -0,0 +1,65 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Complex.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class Complex
+{
+ class RefTypeEmpty
+ {
+ }
+
+ struct Unmanaged
+ {
+ private int a;
+ private int b;
+ }
+
+ struct Managed
+ {
+ private int a;
+ private RefTypeEmpty r;
+ }
+
+ struct ValueType
+ {
+ public int Hello;
+
+ public ValueType()
+ {
+ Hello = 42;
+ }
+ }
+
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ var unmanaged = new Unmanaged();
+ var managed = new Managed();
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Constructors.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Constructors.cs
new file mode 100644
index 000000000..e64bfe1f7
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Constructors.cs
@@ -0,0 +1,53 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Constructors.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class Constructors
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ struct ValueType
+ {
+ public int Hello;
+
+ public ValueType()
+ {
+ Hello = new RefType().Hello;
+ }
+ }
+
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ ValueType value = new ValueType();
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Functions.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Functions.cs
new file mode 100644
index 000000000..a1f1abc9f
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Functions.cs
@@ -0,0 +1,69 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Functions.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class Functions
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ // This wouldn't compile anyways, but the analyzer shouldn't hang
+ static int Recursion(int i)
+ {
+ if (i == 0) return new RefType().Hello;
+ return Recursion(i - 1);
+ }
+
+ static int MutualRecursion1(int i)
+ {
+ if (i == 0) return new RefType().Hello;
+ return MutualRecursion2(i - 1);
+ }
+
+ static int MutualRecursion2(int i)
+ {
+ if (i == 0) return 0;
+ return MutualRecursion1(i - 1);
+ }
+
+ static int AnotherFunction()
+ {
+ return new RefType().Hello;
+ }
+
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ int result = AnotherFunction();
+ int rec1 = Recursion(10);
+ int rec2 = MutualRecursion1(10);
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/ILGPUTypesIntrinsics.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/ILGPUTypesIntrinsics.cs
new file mode 100644
index 000000000..357aaaa37
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/ILGPUTypesIntrinsics.cs
@@ -0,0 +1,52 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: ILGPUTypesIntrinsics.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.Runtime;
+using ILGPU.Runtime.Cuda;
+using ILGPU.Algorithms.Random;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class ILGPUTypesIntrinsics
+{
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ var a = input.SubView(0, 10);
+ int b = a[index];
+ int c = Warp.WarpIdx;
+ Group.Barrier();
+
+ // Strings should be allowed for this and debug.
+ // We will be conservative in our analysis and ignore all strings.
+ CudaAsm.Emit("");
+
+ // Algorithms should also be allowed.
+ // RNGView is just an example of a managed type in Algorithms.
+ var rngView = new RNGView();
+ rngView.Next();
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/LoadDiscovery.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/LoadDiscovery.cs
new file mode 100644
index 000000000..4edab3c20
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/LoadDiscovery.cs
@@ -0,0 +1,75 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: LoadDiscovery.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class LoadDiscovery
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ // Separate kernels so we can observe multiple analyses
+ static void Kernel1(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Kernel2(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Kernel3(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Kernel4(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Kernel5(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Kernel6(Index1D index, ArrayView input)
+ {
+ int result = new RefType().Hello;
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ // Also make sure kernels loaded twice aren't analyzed twice
+ var kernel1 = accelerator.LoadStreamKernel>(Kernel1);
+ var twice = accelerator.LoadStreamKernel>(Kernel1);
+
+ var kernel2 =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel2);
+ var kernel3 =
+ accelerator.LoadImplicitlyGroupedStreamKernel>(
+ Kernel3, 32);
+
+ var kernel4 = accelerator.LoadKernel>(Kernel4);
+ var kernel5 = accelerator.LoadAutoGroupedKernel>(Kernel5);
+ var kernel6 =
+ accelerator.LoadImplicitlyGroupedKernel>(Kernel6, 32);
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/PartialMethods.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/PartialMethods.cs
new file mode 100644
index 000000000..d7d895305
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/PartialMethods.cs
@@ -0,0 +1,57 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: PartialMethods.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType.PartialMethods;
+
+class RefType
+{
+ public int Hello => 42;
+}
+
+partial class Foo
+{
+ public static partial int Bar(int i);
+}
+
+partial class Foo
+{
+ public static partial int Bar(int i)
+ {
+ RefType r = new RefType();
+ return r.Hello + i;
+ }
+}
+
+class PartialMethods
+{
+ static void Kernel(Index1D index, ArrayView view)
+ {
+ view[index] = Foo.Bar(10);
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Simple.cs b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Simple.cs
new file mode 100644
index 000000000..ec225ac00
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Programs/ManagedType/Simple.cs
@@ -0,0 +1,44 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: Simple.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.Runtime;
+
+namespace ILGPU.Analyzers.Tests.Programs.ManagedType;
+
+class Simple
+{
+ class RefType
+ {
+ public int Hello => 42;
+ }
+
+ static void Kernel(Index1D index, ArrayView input)
+ {
+ var refType = new RefType();
+ input[index] = input[index] + refType.Hello;
+ }
+
+ static void Run()
+ {
+ using var context = Context.CreateDefault();
+ var device = context.GetPreferredDevice(false);
+ using var accelerator = device.CreateAccelerator(context);
+
+ using var input = accelerator.Allocate1D(1024);
+
+ var kernel =
+ accelerator.LoadAutoGroupedStreamKernel>(Kernel);
+
+ kernel(input.IntExtent, input.View);
+
+ accelerator.Synchronize();
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Arrays.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Arrays.verified.txt
new file mode 100644
index 000000000..fb4ff8b6e
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Arrays.verified.txt
@@ -0,0 +1,22 @@
+[
+ {
+ Id: ILA004,
+ Title: Array of managed types in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (37,25)-(37,40),
+ MessageFormat: Type '{0}' is an array of type '{1}', which is a managed type. Arrays of managed types cannot be used in kernels.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Arrays.RefType[]' is an array of type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Arrays.RefType', which is a managed type. Arrays of managed types cannot be used in kernels.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (37,26)-(37,39),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Arrays.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Complex.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Complex.verified.txt
new file mode 100644
index 000000000..bad99fa9b
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Complex.verified.txt
@@ -0,0 +1,12 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (46,22)-(46,35),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Complex.Managed' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Constructors.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Constructors.verified.txt
new file mode 100644
index 000000000..70fe334d2
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Constructors.verified.txt
@@ -0,0 +1,12 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (28,20)-(28,33),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Constructors.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Functions.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Functions.verified.txt
new file mode 100644
index 000000000..25d483611
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Functions.verified.txt
@@ -0,0 +1,32 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (31,27)-(31,40),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Functions.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (25,27)-(25,40),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Functions.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (43,15)-(43,28),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Functions.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=ILGPUTypesIntrinsics.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=ILGPUTypesIntrinsics.verified.txt
new file mode 100644
index 000000000..ad47dbb93
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=ILGPUTypesIntrinsics.verified.txt
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=LoadDiscovery.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=LoadDiscovery.verified.txt
new file mode 100644
index 000000000..09eeec3d6
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=LoadDiscovery.verified.txt
@@ -0,0 +1,62 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (25,21)-(25,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (30,21)-(30,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (35,21)-(35,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (40,21)-(40,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (45,21)-(45,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (50,21)-(50,34),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.LoadDiscovery.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=PartialMethods.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=PartialMethods.verified.txt
new file mode 100644
index 000000000..e7a029638
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=PartialMethods.verified.txt
@@ -0,0 +1,22 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (29,20)-(29,33),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.PartialMethods.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (30,15)-(30,16),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.PartialMethods.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Simple.verified.txt b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Simple.verified.txt
new file mode 100644
index 000000000..adf2a8458
--- /dev/null
+++ b/Src/ILGPU.Analyzers.Tests/Snapshots/ManagedTypeAnalyzer.FileTests_file=Simple.verified.txt
@@ -0,0 +1,22 @@
+[
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (24,22)-(24,35),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Simple.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ },
+ {
+ Id: ILA003,
+ Title: Managed type in kernel,
+ Severity: Warning,
+ WarningLevel: 1,
+ Location: : (25,38)-(25,45),
+ MessageFormat: Type '{0}' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Message: Type 'ILGPU.Analyzers.Tests.Programs.ManagedType.Simple.RefType' is a managed type. Managed types like classes cannot be used in kernels, except for arrays of unmanaged types.,
+ Category: Usage
+ }
+]
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers/AnalyzerReleases.Unshipped.md b/Src/ILGPU.Analyzers/AnalyzerReleases.Unshipped.md
index ddc574b58..3d29a0ce6 100644
--- a/Src/ILGPU.Analyzers/AnalyzerReleases.Unshipped.md
+++ b/Src/ILGPU.Analyzers/AnalyzerReleases.Unshipped.md
@@ -6,4 +6,6 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|-------
ILA001 | CodeGeneration | Error | SourceGenerator
-ILA002 | CodeGeneration | Error | SourceGenerator
\ No newline at end of file
+ILA002 | CodeGeneration | Error | SourceGenerator
+ILA003 | Usage | Warning | Analyzer
+ILA004 | Usage | Warning | Analyzer
diff --git a/Src/ILGPU.Analyzers/DiagnosticCategory.cs b/Src/ILGPU.Analyzers/DiagnosticCategory.cs
new file mode 100644
index 000000000..d89d0099b
--- /dev/null
+++ b/Src/ILGPU.Analyzers/DiagnosticCategory.cs
@@ -0,0 +1,18 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2023-2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: DiagnosticCategory.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+namespace ILGPU.Analyzers
+{
+ public static class DiagnosticCategory
+ {
+ public static string Usage => "Usage";
+ }
+}
diff --git a/Src/ILGPU.Analyzers/ILGPU.Analyzers.csproj b/Src/ILGPU.Analyzers/ILGPU.Analyzers.csproj
index c6e94e3ff..239e33f12 100644
--- a/Src/ILGPU.Analyzers/ILGPU.Analyzers.csproj
+++ b/Src/ILGPU.Analyzers/ILGPU.Analyzers.csproj
@@ -36,6 +36,16 @@
+
+ True
+ True
+ ILA003_ManagedTypeInKernel.Designer.cs
+
+
+ True
+ True
+ ILA004_ManagedTypeArrayInKernel.Designer.cs
+
True
True
diff --git a/Src/ILGPU.Analyzers/InterleaveFieldsGenerator.cs b/Src/ILGPU.Analyzers/InterleaveFieldsGenerator.cs
index 0506a69a4..9ed076aa9 100644
--- a/Src/ILGPU.Analyzers/InterleaveFieldsGenerator.cs
+++ b/Src/ILGPU.Analyzers/InterleaveFieldsGenerator.cs
@@ -34,7 +34,7 @@ public class InterleaveFieldsGenerator : IIncrementalGenerator
id: "ILA001",
title: ErrorMessages.StructMustBePartial_Title,
messageFormat: ErrorMessages.StructMustBePartial_Message,
- category: ErrorMessages.Usage_Category,
+ category: DiagnosticCategory.Usage,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
@@ -42,7 +42,7 @@ public class InterleaveFieldsGenerator : IIncrementalGenerator
id: "ILA002",
title: ErrorMessages.ContainingTypeMustBePartial_Title,
messageFormat: ErrorMessages.ContainingTypeMustBePartial_Message,
- category: ErrorMessages.Usage_Category,
+ category: DiagnosticCategory.Usage,
defaultSeverity: DiagnosticSeverity.Error,
isEnabledByDefault: true);
diff --git a/Src/ILGPU.Analyzers/KernelAnalyzer.cs b/Src/ILGPU.Analyzers/KernelAnalyzer.cs
new file mode 100644
index 000000000..a306e75ed
--- /dev/null
+++ b/Src/ILGPU.Analyzers/KernelAnalyzer.cs
@@ -0,0 +1,110 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2023-2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: KernelAnalyzer.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using System.Collections.Concurrent;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Operations;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace ILGPU.Analyzers
+{
+ ///
+ /// Base analyzer that can be used to implement diagnostic analyzers that operate on
+ /// kernel method bodies.
+ ///
+ public abstract class KernelAnalyzer : DiagnosticAnalyzer
+ {
+ private readonly ImmutableHashSet kernelLoadNames =
+ ImmutableHashSet.Create(
+ "LoadKernel",
+ "LoadAutoGroupedKernel",
+ "LoadImplicitlyGroupedKernel",
+ "LoadStreamKernel",
+ "LoadAutoGroupedStreamKernel",
+ "LoadImplicitlyGroupedStreamKernel"
+ );
+
+ private readonly ConcurrentDictionary seen = new();
+
+ ///
+ /// Called for every kernel body.
+ ///
+ ///
+ /// The analysis context used to report diagnostics.
+ ///
+ /// The operation.
+ protected abstract void AnalyzeKernelBody(
+ OperationAnalysisContext context,
+ IOperation bodyOp);
+
+ public override void Initialize(AnalysisContext context)
+ {
+ context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
+ context.EnableConcurrentExecution();
+
+ seen.Clear();
+
+ // Subscribe to semantic (compile time) action invocation
+ // Subscribe only to method invocations (we want to find the kernel load call)
+ context.RegisterOperationAction(AnalyzeOperation, OperationKind.Invocation);
+ }
+
+ private void AnalyzeOperation(OperationAnalysisContext context)
+ {
+ if (seen.ContainsKey(context.Operation)) return;
+
+ if (context.Operation is not IInvocationOperation invocationOperation ||
+ context.Operation.Syntax is not InvocationExpressionSyntax)
+ return;
+
+ var methodSymbol = invocationOperation.TargetMethod;
+
+ if (methodSymbol.MethodKind != MethodKind.Ordinary
+ || !kernelLoadNames.Contains(methodSymbol.Name))
+ return;
+
+ var kernelArg = invocationOperation.Arguments.FirstOrDefault(x =>
+ x.Parameter?.Type.TypeKind == TypeKind.Delegate);
+
+ // TODO: support expressions that return delegate (probably requires dataflow)
+ if (kernelArg?.Value is
+ IDelegateCreationOperation
+ delegateOp)
+ {
+ // We should always have a semantic model since we subscribed
+ // to semantic analysis
+ var semanticModel = context.Operation.SemanticModel!;
+
+ var bodyOp = delegateOp.Target switch
+ {
+ IMethodReferenceOperation refOp => MethodUtil.GetMethodBody(
+ semanticModel,
+ refOp.Method),
+ IAnonymousFunctionOperation anonymousOp => anonymousOp.Body,
+ _ => null,
+ };
+
+ if (bodyOp is not null)
+ {
+ // If we couldn't add it, another thread got here first.
+ bool added = seen.TryAdd(bodyOp, true);
+ if (added)
+ {
+ AnalyzeKernelBody(context, bodyOp);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers/ManagedTypeAnalyzer.cs b/Src/ILGPU.Analyzers/ManagedTypeAnalyzer.cs
new file mode 100644
index 000000000..8f999de1a
--- /dev/null
+++ b/Src/ILGPU.Analyzers/ManagedTypeAnalyzer.cs
@@ -0,0 +1,169 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: ManagedTypeAnalyzer.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.Diagnostics;
+using System.Collections.Generic;
+using Microsoft.CodeAnalysis.Operations;
+using ILGPU.Analyzers.Resources;
+
+namespace ILGPU.Analyzers
+{
+ [DiagnosticAnalyzer(LanguageNames.CSharp)]
+ public class ManagedTypeAnalyzer : KernelAnalyzer
+ {
+ private static readonly DiagnosticDescriptor GeneralDiagnosticRule = new(
+ id: "ILA003",
+ title: ErrorMessages.ManagedTypeInKernel_Title,
+ messageFormat: ErrorMessages.ManagedTypeInKernel_Message,
+ category: DiagnosticCategory.Usage,
+ defaultSeverity: DiagnosticSeverity.Warning,
+ isEnabledByDefault: true
+ );
+
+ private static readonly DiagnosticDescriptor ArrayDiagnosticRule = new(
+ id: "ILA004",
+ title: ErrorMessages.ManagedTypeArrayInKernel_Title,
+ messageFormat: ErrorMessages.ManagedTypeArrayInKernel_Message,
+ category: DiagnosticCategory.Usage,
+ defaultSeverity: DiagnosticSeverity.Warning,
+ isEnabledByDefault: true
+ );
+
+ private const string ILGPUAssemblyName = "ILGPU";
+ private const string AlgorithmsAssemblyName = "ILGPU.Algorithms";
+
+ public override ImmutableArray
+ SupportedDiagnostics { get; } =
+ ImmutableArray.Create(GeneralDiagnosticRule, ArrayDiagnosticRule);
+
+ protected override void AnalyzeKernelBody(OperationAnalysisContext context,
+ IOperation bodyOp)
+ {
+ Stack bodies = new Stack();
+
+ // Prevents infinite looping when functions are recursive
+ // Also prevents analyzing syntax (like collection expressions) that appear
+ // twice in descendants for some unknown reason.
+ // Costs us more memory than I would like, but not sure if we have a choice.
+ HashSet seenLocations = new HashSet();
+
+ bodies.Push(bodyOp);
+
+ // We will always have a semantic model because KernelAnalyzer subscribes
+ // to semantic analysis
+ var semanticModel = context.Operation.SemanticModel!;
+
+ while (bodies.Count != 0)
+ {
+ var op = bodies.Pop();
+
+ foreach (var descendant in op.DescendantsAndSelf())
+ {
+ var descendantLocation = descendant.Syntax.GetLocation();
+ if (!seenLocations.Add(descendantLocation)) continue;
+
+ AnalyzeKernelOperation(context, descendant);
+
+ var invokedSymbol = GetInvokedSymbolIfExists(descendant);
+ if (invokedSymbol is null) continue;
+
+ if (IsILGPUSymbol(invokedSymbol)) continue;
+
+ var methodBodyOp =
+ MethodUtil.GetMethodBody(semanticModel, invokedSymbol);
+ if (methodBodyOp is null) continue;
+
+ var methodBodyLocation = methodBodyOp.Syntax.GetLocation();
+ if (!seenLocations.Contains(methodBodyLocation))
+ {
+ bodies.Push(methodBodyOp);
+ }
+ }
+ }
+ }
+
+ private void AnalyzeKernelOperation(OperationAnalysisContext context,
+ IOperation op)
+ {
+ if (op.Type is null)
+ return;
+
+ if (op.Type.IsUnmanagedType)
+ return;
+
+ if (IsILGPUSymbol(op.Type))
+ return;
+
+ if (op.Type.SpecialType == SpecialType.System_String)
+ return;
+
+ if (op.Type is IArrayTypeSymbol arrayTypeSymbol)
+ {
+ if (arrayTypeSymbol.ElementType.IsUnmanagedType)
+ return;
+
+ string first = arrayTypeSymbol.ToDisplayString();
+ string second = arrayTypeSymbol.ElementType.ToDisplayString();
+
+ var arrayDiagnostic =
+ Diagnostic.Create(ArrayDiagnosticRule,
+ op.Syntax.GetLocation(), first, second);
+ context.ReportDiagnostic(arrayDiagnostic);
+ }
+ else
+ {
+ var generalDiagnostic =
+ Diagnostic.Create(GeneralDiagnosticRule,
+ op.Syntax.GetLocation(),
+ op.Type.ToDisplayString());
+ context.ReportDiagnostic(generalDiagnostic);
+ }
+ }
+
+ ///
+ /// Gets the symbol for a method a given operation invokes, if the operation
+ /// invokes anything at all. Only looks at direct invocations, meaning descendants
+ /// will not be explored.
+ ///
+ /// The operation to analyze.
+ ///
+ /// The method symbol representing the method op invokes. This could be a
+ /// regular method or a constructor. Null if op doesn't invoke anything
+ /// directly.
+ ///
+ private IMethodSymbol? GetInvokedSymbolIfExists(IOperation op) =>
+ op switch
+ {
+ IInvocationOperation invocationOperation => invocationOperation
+ .TargetMethod,
+ IObjectCreationOperation
+ {
+ Constructor: not null
+ } creationOperation => creationOperation.Constructor,
+ _ => null
+ };
+
+ ///
+ /// Whether a given symbol is a symbol from an ILGPU assembly.
+ ///
+ /// The symbol to check.
+ ///
+ /// Whether symbol is in the ILGPU or ILGPU.Algorithms assemblies.
+ ///
+ private static bool IsILGPUSymbol(ISymbol symbol)
+ {
+ return symbol.ContainingAssembly?.Name is ILGPUAssemblyName
+ or AlgorithmsAssemblyName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers/MethodUtil.cs b/Src/ILGPU.Analyzers/MethodUtil.cs
new file mode 100644
index 000000000..16d111c1a
--- /dev/null
+++ b/Src/ILGPU.Analyzers/MethodUtil.cs
@@ -0,0 +1,56 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU
+// Copyright (c) 2024 ILGPU Project
+// www.ilgpu.net
+//
+// File: MethodUtil.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+using Microsoft.CodeAnalysis;
+
+namespace ILGPU.Analyzers
+{
+ public static class MethodUtil
+ {
+ ///
+ /// Gets the body operation of a given method.
+ ///
+ ///
+ /// The semantic model for the compilation that includes symbol.
+ ///
+ /// The method symbol to get the body of.
+ ///
+ /// The body of the method represented by symbol. If symbol is a
+ /// partial method, the operation representing the implementation is returned.
+ /// Null if the operation could not be resolved, for example, if symbol
+ /// is partial and there is no implementation part.
+ ///
+ public static IOperation? GetMethodBody(SemanticModel model, IMethodSymbol symbol)
+ {
+ return symbol switch
+ {
+ {
+ IsPartialDefinition: false,
+ DeclaringSyntaxReferences: { Length: > 0 } refs
+ } => GetOperationIfInTree(model, refs[0].GetSyntax()),
+ {
+ PartialImplementationPart:
+ {
+ DeclaringSyntaxReferences: { Length: > 0 } refs
+ },
+ } => GetOperationIfInTree(model, refs[0].GetSyntax()),
+ _ => null
+ };
+ }
+
+ private static IOperation? GetOperationIfInTree(SemanticModel model,
+ SyntaxNode node)
+ {
+ var root = model.SyntaxTree.GetRoot();
+ return root.Contains(node) ? model.GetOperation(node) : null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers/Properties/launchSettings.json b/Src/ILGPU.Analyzers/Properties/launchSettings.json
index 54dcc924f..0b83fbc0c 100644
--- a/Src/ILGPU.Analyzers/Properties/launchSettings.json
+++ b/Src/ILGPU.Analyzers/Properties/launchSettings.json
@@ -1,8 +1,12 @@
{
"profiles": {
- "ILGPU.Analyzers": {
+ "InterleaveFields": {
"commandName": "DebugRoslynComponent",
"targetProject": "..\\..\\Samples\\InterleaveFields\\InterleaveFields.csproj"
+ },
+ "RefType": {
+ "commandName": "DebugRoslynComponent",
+ "targetProject": "..\\..\\Samples\\RefTypeAnalyzer\\RefTypeAnalyzer.csproj"
}
}
}
\ No newline at end of file
diff --git a/Src/ILGPU.Analyzers/Resources/ErrorMessages.Designer.cs b/Src/ILGPU.Analyzers/Resources/ErrorMessages.Designer.cs
index fcf31f0c6..d182e6d95 100644
--- a/Src/ILGPU.Analyzers/Resources/ErrorMessages.Designer.cs
+++ b/Src/ILGPU.Analyzers/Resources/ErrorMessages.Designer.cs
@@ -1,7 +1,6 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -12,46 +11,32 @@ namespace ILGPU.Analyzers.Resources {
using System;
- ///
- /// A strongly-typed resource class, for looking up localized strings, etc.
- ///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class ErrorMessages {
- private static global::System.Resources.ResourceManager resourceMan;
+ private static System.Resources.ResourceManager resourceMan;
- private static global::System.Globalization.CultureInfo resourceCulture;
+ private static System.Globalization.CultureInfo resourceCulture;
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal ErrorMessages() {
}
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Resources.ResourceManager ResourceManager {
get {
- if (object.ReferenceEquals(resourceMan, null)) {
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILGPU.Analyzers.Resources.ErrorMessages", typeof(ErrorMessages).Assembly);
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ILGPU.Analyzers.Resources.ErrorMessages", typeof(ErrorMessages).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@@ -60,48 +45,51 @@ internal ErrorMessages() {
}
}
- ///
- /// Looks up a localized string similar to The type '{0}' containing '{1}' must be partial.
- ///
+ internal static string StructMustBePartial_Message {
+ get {
+ return ResourceManager.GetString("StructMustBePartial_Message", resourceCulture);
+ }
+ }
+
+ internal static string StructMustBePartial_Title {
+ get {
+ return ResourceManager.GetString("StructMustBePartial_Title", resourceCulture);
+ }
+ }
+
internal static string ContainingTypeMustBePartial_Message {
get {
return ResourceManager.GetString("ContainingTypeMustBePartial_Message", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Containing type must be partial.
- ///
internal static string ContainingTypeMustBePartial_Title {
get {
return ResourceManager.GetString("ContainingTypeMustBePartial_Title", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to The struct '{0}' must be partial.
- ///
- internal static string StructMustBePartial_Message {
+ internal static string ManagedTypeInKernel_Message {
get {
- return ResourceManager.GetString("StructMustBePartial_Message", resourceCulture);
+ return ResourceManager.GetString("ManagedTypeInKernel_Message", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Struct must be partial.
- ///
- internal static string StructMustBePartial_Title {
+ internal static string ManagedTypeInKernel_Title {
get {
- return ResourceManager.GetString("StructMustBePartial_Title", resourceCulture);
+ return ResourceManager.GetString("ManagedTypeInKernel_Title", resourceCulture);
+ }
+ }
+
+ internal static string ManagedTypeArrayInKernel_Message {
+ get {
+ return ResourceManager.GetString("ManagedTypeArrayInKernel_Message", resourceCulture);
}
}
- ///
- /// Looks up a localized string similar to Usage.
- ///
- internal static string Usage_Category {
+ internal static string ManagedTypeArrayInKernel_Title {
get {
- return ResourceManager.GetString("Usage_Category", resourceCulture);
+ return ResourceManager.GetString("ManagedTypeArrayInKernel_Title", resourceCulture);
}
}
}
diff --git a/Src/ILGPU.Analyzers/Resources/ErrorMessages.resx b/Src/ILGPU.Analyzers/Resources/ErrorMessages.resx
index 6603f4ca7..f6f460cc5 100644
--- a/Src/ILGPU.Analyzers/Resources/ErrorMessages.resx
+++ b/Src/ILGPU.Analyzers/Resources/ErrorMessages.resx
@@ -1,135 +1,45 @@
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- The type '{0}' containing '{1}' must be partial
-
-
- Containing type must be partial
-
-
- The struct '{0}' must be partial
-
-
- Struct must be partial
-
-
- Usage
-
\ No newline at end of file