Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NativeAOT] Implementation Proposal for AOT-friendly IIRReader API #1232

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6f6ef52
Initial implementation of `IRSerializer` class
IsaMorphic May 21, 2024
73180b8
Rename `IRSerializer` to `IRWriter`
IsaMorphic May 21, 2024
053f944
All `Value` writing logic is complete
IsaMorphic May 21, 2024
ee24d70
change parameter names
IsaMorphic May 21, 2024
0602f13
Oops :3
IsaMorphic May 21, 2024
0b0b10f
Implement proper type handling for Value instances
IsaMorphic May 21, 2024
cec4690
Abstracted `IRWriter` to `IIRWriter` and `BinaryIRWriter`
IsaMorphic May 24, 2024
3d3d113
Added IR type serialization
IsaMorphic May 24, 2024
c9a2be1
Final touches
IsaMorphic May 24, 2024
505ba05
Fix compiler errors from missing using statements
IsaMorphic May 25, 2024
b357926
Added considerations for potentially replacing `IDumpable`
IsaMorphic May 25, 2024
8ec5601
Implement requested changes
IsaMorphic Jun 4, 2024
11a7434
Fix nits for final review
IsaMorphic Jul 19, 2024
5f74795
One last nit of mine
IsaMorphic Jul 19, 2024
7c961fb
Update copyright headers / fix unused using statements
IsaMorphic Jul 24, 2024
745104b
Fix code styles: line length
IsaMorphic Jul 24, 2024
2508de9
Implementation proposal for `IIRReader` API
IsaMorphic May 25, 2024
712ab5f
Finish concept implementation (purposefully does not compile due to m…
IsaMorphic May 25, 2024
400c3c2
Fix copyright header
IsaMorphic May 25, 2024
59c63ab
Fixes from rebase
IsaMorphic May 25, 2024
e2ba9b6
Change up constructor
IsaMorphic May 31, 2024
49dc4ec
Expanded TypeKind API
IsaMorphic May 31, 2024
50438ca
More `.Read` implementations
IsaMorphic May 31, 2024
6130b4f
More work on deserializers
IsaMorphic Jul 24, 2024
841ad87
Rebase fixes and a little more work
IsaMorphic Jul 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions Src/ILGPU.Analyzers/ReaderDelegatesGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2024 ILGPU Project
// www.ilgpu.net
//
// File: ReaderDelegatesGenerator.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;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ILGPU.Analyzers
{
[Generator]
public class ReaderDelegatesGenerator : ISourceGenerator
{
private class ValueKindReciever : ISyntaxReceiver
{
private readonly ConcurrentDictionary<string, string> valueKinds;

public IReadOnlyDictionary<string, string> ValueKinds => valueKinds;

public ValueKindReciever()
{
valueKinds = new ConcurrentDictionary<string, string>();
}

public void OnVisitSyntaxNode(SyntaxNode node)
{
AttributeSyntax? attribute;
if (node is ClassDeclarationSyntax cl &&
cl.Parent is NamespaceDeclarationSyntax ns &&
ns.Name.ToString().StartsWith("ILGPU.IR.Values") &&
(attribute = cl.AttributeLists.SelectMany(x => x.Attributes)
.SingleOrDefault(attr => attr.Name.ToString() == "ValueKind"))
is not null)
{
var valueKind = attribute.ArgumentList?
.Arguments.SingleOrDefault()
.Expression.ToString() ?? throw new InvalidOperationException("Malformed input syntax.");
var valueClass = cl.Identifier.ToString();
valueKinds.TryAdd(valueKind, valueClass);
}
}
}

public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new ValueKindReciever());
}

public void Execute(GeneratorExecutionContext context)
{
var valueKindReciever = context.SyntaxReceiver as ValueKindReciever;
if (valueKindReciever is not null)
{
var builder = new StringBuilder();

builder.AppendLine("using ILGPU.IR.Values;");
builder.AppendLine();
builder.AppendLine("namespace ILGPU.IR");
builder.AppendLine("{");
builder.AppendLine(" public static partial class ValueKinds");
builder.AppendLine(" {");
builder.AppendLine(" static ValueKinds()");
builder.AppendLine(" {");
foreach (var kv in valueKindReciever.ValueKinds)
{
builder.AppendLine($" _readerDelegates.TryAdd({kv.Key}, {kv.Value}.Read);");
}
builder.AppendLine(" }");
builder.AppendLine(" }");
builder.AppendLine("}");

context.AddSource("ValueKinds.g.cs", builder.ToString());
}
}
}
}
6 changes: 6 additions & 0 deletions Src/ILGPU/ILGPU.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
<PackageReference Include="T4.Build" Version="0.2.4" PrivateAssets="All" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ILGPU.Analyzers\ILGPU.Analyzers.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<None Include="AtomicFunctions.cs">
<DesignTime>True</DesignTime>
Expand Down
30 changes: 29 additions & 1 deletion Src/ILGPU/IR/IRContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2018-2023 ILGPU Project
// Copyright (c) 2018-2024 ILGPU Project
// www.ilgpu.net
//
// File: IRContext.cs
Expand All @@ -12,6 +12,7 @@
using ILGPU.Frontend;
using ILGPU.IR.Analyses;
using ILGPU.IR.Construction;
using ILGPU.IR.Serialization;
using ILGPU.IR.Transformations;
using ILGPU.IR.Types;
using ILGPU.IR.Values;
Expand Down Expand Up @@ -498,6 +499,33 @@ public void Transform(in Transformer transformer)
Parallel.ForEach(toTransform, gcDelegate);
}

/// <summary>
/// Serializes this instance using the given <see cref="IIRWriter"/>.
/// </summary>
/// <typeparam name="T">
/// The specific type of <see cref="IIRWriter"/>.
/// </typeparam>
/// <param name="writer">
/// The writer to use for serialization.
/// </param>
public void Write<T>(T writer) where T : IIRWriter
{
var allMethods = GetMethodCollection(new MethodCollections.AllMethods());
foreach (var method in allMethods)
{
foreach (var param in method.Parameters)
param.Write(writer);

foreach (var block in method.Blocks)
{
foreach (var entry in block)
entry.Value.Write(writer);

block.Terminator?.Write(writer);
}
}
}

/// <summary>
/// Dumps the IR context to the given text writer.
/// </summary>
Expand Down
116 changes: 116 additions & 0 deletions Src/ILGPU/IR/Serialization/BinaryIRReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2024 ILGPU Project
// www.ilgpu.net
//
// File: BinaryIRReader.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.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;

namespace ILGPU.IR.Serialization
{
/// <summary>
/// Wrapper class around <see cref="BinaryReader"/> for deserializing IR types and values.
/// </summary>
public sealed class BinaryIRReader : IIRReader
{
private readonly BinaryReader reader;

/// <inheritdoc/>
public IIRMappingContext Context { get; }

/// <summary>
/// Wraps an instance of <see cref="BinaryIRReader"/>
/// around a given <see cref="Stream"/>.
/// </summary>
/// <param name="stream">
/// The <see cref="Stream"/> instance to wrap.
/// </param>
/// <param name="encoding">
/// The <see cref="Encoding"/> to use for
/// deserializing <see cref="string"/> values.
/// </param>
/// <param name="context">
/// A mapping context instance to use for deserialization.
/// </param>
public BinaryIRReader(Stream stream, Encoding encoding, IIRMappingContext context)
{
reader = new BinaryReader(stream, encoding);
Context = context;
}


/// <inheritdoc/>
public bool Read(out int value)
{
try
{
value = reader.ReadInt32();
return true;
}
catch (EndOfStreamException)
{
value = default;
return false;
}
}

/// <inheritdoc/>
public bool Read(out long value)
{
try
{
value = reader.ReadInt64();
return true;
}
catch (EndOfStreamException)
{
value = default;
return false;
}
}

/// <inheritdoc/>
public bool Read([NotNullWhen(true)] out string? value)
{
try
{
value = reader.ReadString();
return true;
}
catch (EndOfStreamException)
{
value = default;
return false;
}
}

/// <inheritdoc/>
public bool Read<T>(out T value)
where T : unmanaged, Enum
{
try
{
value = (T)Enum.ToObject(typeof(T), reader.ReadInt32());
return true;
}
catch (EndOfStreamException)
{
value = default;
return false;
}
}

/// <summary>
/// Disposes of the wrapped <see cref="BinaryReader"/> instance.
/// </summary>
public void Dispose() => ((IDisposable)reader).Dispose();
}
}
68 changes: 68 additions & 0 deletions Src/ILGPU/IR/Serialization/BinaryIRWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// ---------------------------------------------------------------------------------------
// ILGPU
// Copyright (c) 2024 ILGPU Project
// www.ilgpu.net
//
// File: BinaryIRWriter.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.IO;
using System.Text;

namespace ILGPU.IR.Serialization
{
/// <summary>
/// Wrapper class around <see cref="BinaryWriter"/>
/// for serializing IR types and values.
/// </summary>
public sealed class BinaryIRWriter : DisposeBase, IIRWriter
{
private readonly BinaryWriter writer;

/// <summary>
/// Wraps an instance of <see cref="BinaryIRWriter"/>
/// around a given <see cref="Stream"/>.
/// </summary>
/// <param name="stream">
/// The <see cref="Stream"/> instance to wrap.
/// </param>
/// <param name="encoding">
/// The <see cref="Encoding"/> to use for
/// serializing <see cref="string"/> values.
/// </param>
public BinaryIRWriter(Stream stream, Encoding encoding)
{
writer = new BinaryWriter(stream, encoding);
}

/// <inheritdoc/>
public void Write(string tag, int value) =>
writer.Write(value);

/// <inheritdoc/>
public void Write(string tag, long value) =>
writer.Write(value);

/// <inheritdoc/>
public void Write(string tag, string value) =>
writer.Write(value);

/// <inheritdoc/>
public void Write<T>(string tag, T value)
where T : unmanaged, Enum =>
writer.Write(Convert.ToInt32(value));

/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
if (disposing)
writer.Dispose();
base.Dispose(disposing);
}
}
}
Loading