From 1eb8e432068a76f8283df23de302c83cee1ba9f0 Mon Sep 17 00:00:00 2001 From: Adriano Carlos Verona Date: Thu, 7 Mar 2024 23:27:28 -0500 Subject: [PATCH] adds support for loading local Inline Arrary element at index 0 (#257) --- .../Tests/Unit/InlineArrayTests.cs | 27 +++++++++++++++++-- Cecilifier.Core/AST/AssignmentVisitor.cs | 5 ++-- Cecilifier.Core/AST/ExpressionVisitor.cs | 6 +++++ Cecilifier.Core/AST/InlineArrayProcessor.cs | 19 ++++++++----- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Cecilifier.Core.Tests/Tests/Unit/InlineArrayTests.cs b/Cecilifier.Core.Tests/Tests/Unit/InlineArrayTests.cs index 7e1acad1..9efafe76 100644 --- a/Cecilifier.Core.Tests/Tests/Unit/InlineArrayTests.cs +++ b/Cecilifier.Core.Tests/Tests/Unit/InlineArrayTests.cs @@ -53,7 +53,7 @@ public struct IntBuffer } [Test] - public void AccessToFirstElement_MapsTo_PrivateImplementationDetailsInlineArrayFirstElementRefMethod() + public void AssignmentToFirstElement_MapsTo_PrivateImplementationDetailsInlineArrayFirstElementRefMethod() { var result = RunCecilifier(""" var buffer = new IntBuffer(); @@ -84,6 +84,29 @@ public struct IntBuffer """)); } + [Test] + public void AccessToFirstElement_MapsTo_PrivateImplementationDetailsInlineArrayFirstElementRefMethod() + { + var result = RunCecilifier(""" + var buffer = new IntBuffer(); + buffer[0] = 42; + System.Console.WriteLine(buffer[0]); + + [System.Runtime.CompilerServices.InlineArray(10)] + public struct IntBuffer + { + private int _element0; + } + """); + + var cecilified = result.GeneratedCode.ReadToEnd(); + + Assert.That(cecilified, Does.Match(""" + (il_topLevelMain_\d+\.Emit\(OpCodes\.)Call, gi_inlineArrayFirstElementRef_\d+\); + \s+\1Ldind_I4\); + \s+\1Call,.+ImportReference\(.+ResolveMethod\(typeof\(System.Console\), "WriteLine".+\); + """)); + } + // Access to not first element - // } diff --git a/Cecilifier.Core/AST/AssignmentVisitor.cs b/Cecilifier.Core/AST/AssignmentVisitor.cs index 2a569cb9..234d494c 100644 --- a/Cecilifier.Core/AST/AssignmentVisitor.cs +++ b/Cecilifier.Core/AST/AssignmentVisitor.cs @@ -45,11 +45,10 @@ internal AssignmentVisitor(IVisitorContext ctx, string ilVar) : base(ctx) public override void VisitElementAccessExpression(ElementAccessExpressionSyntax node) { var lastInstructionLoadingRhs = Context.CurrentLine; - if (InlineArrayProcessor.HandleInlineArrayElementAccess(Context, ilVar, node)) + if (InlineArrayProcessor.TryHandleInlineArrayElementAccess(Context, ilVar, node, out var elementType)) { Context.MoveLinesToEnd(InstructionPrecedingValueToLoad, lastInstructionLoadingRhs); - var arrayElementType = Context.SemanticModel.GetTypeInfo(node).Type.EnsureNotNull(); - Context.EmitCilInstruction(ilVar, arrayElementType.Stind()); + Context.EmitCilInstruction(ilVar, elementType.StindOpCodeFor()); return; } diff --git a/Cecilifier.Core/AST/ExpressionVisitor.cs b/Cecilifier.Core/AST/ExpressionVisitor.cs index fec1f193..243d9ae1 100644 --- a/Cecilifier.Core/AST/ExpressionVisitor.cs +++ b/Cecilifier.Core/AST/ExpressionVisitor.cs @@ -241,6 +241,12 @@ public override void VisitElementAccessExpression(ElementAccessExpressionSyntax return; } + if (InlineArrayProcessor.TryHandleInlineArrayElementAccess(Context, ilVar, node, out var elementType)) + { + Context.EmitCilInstruction(ilVar, elementType.LdindOpCodeFor()); + return; + } + node.Expression.Accept(this); node.ArgumentList.Accept(this); diff --git a/Cecilifier.Core/AST/InlineArrayProcessor.cs b/Cecilifier.Core/AST/InlineArrayProcessor.cs index 6c2ba266..39c242d5 100644 --- a/Cecilifier.Core/AST/InlineArrayProcessor.cs +++ b/Cecilifier.Core/AST/InlineArrayProcessor.cs @@ -77,13 +77,14 @@ static string InlineArrayAsSpanMethodFor(IVisitorContext context, ITypeSymbol in } } - internal static bool HandleInlineArrayElementAccess(IVisitorContext context, string ilVar, ElementAccessExpressionSyntax elementAccess) + internal static bool TryHandleInlineArrayElementAccess(IVisitorContext context, string ilVar, ElementAccessExpressionSyntax elementAccess, out ITypeSymbol elementType) { + elementType = null; if (elementAccess.Expression.IsKind(SyntaxKind.ElementAccessExpression)) return false; - var expSymbol = context.SemanticModel.GetSymbolInfo(elementAccess.Expression).Symbol.EnsureNotNull(); - if (expSymbol.GetMemberType().TryGetAttribute(out _)) + var inlineArrayType = context.SemanticModel.GetSymbolInfo(elementAccess.Expression).Symbol.EnsureNotNull().GetMemberType(); + if (inlineArrayType.TryGetAttribute(out _)) { ExpressionVisitor.Visit(context, ilVar, elementAccess.Expression); Debug.Assert(elementAccess.ArgumentList.Arguments.Count == 1); @@ -91,15 +92,16 @@ internal static bool HandleInlineArrayElementAccess(IVisitorContext context, str var method = string.Empty; if (elementAccess.ArgumentList.Arguments[0].Expression.TryGetLiteralValueFor(out int index) && index == 0) { - method = InlineArrayFirstElementRefMethodFor(context, expSymbol.GetMemberType()); + method = InlineArrayFirstElementRefMethodFor(context, inlineArrayType); } else { context.EmitCilInstruction(ilVar, OpCodes.Ldc_I4, index); - method = InlineArrayElementRefMethodFor(context, expSymbol.GetMemberType()); + method = InlineArrayElementRefMethodFor(context, inlineArrayType); } context.EmitCilInstruction(ilVar, OpCodes.Call, method); + elementType = InlineArrayElementTypeFrom(inlineArrayType); return true; } @@ -132,7 +134,7 @@ private static string PrivateImplementationInlineArrayGenericInstanceMethodFor(I varName, [ context.TypeResolver.Resolve(inlineArrayType), // TBuffer - context.TypeResolver.Resolve(((IFieldSymbol) inlineArrayType.GetMembers().First()).Type) // TElement + context.TypeResolver.Resolve(InlineArrayElementTypeFrom(inlineArrayType)) // TElement ]); foreach (var exp in exps) @@ -143,6 +145,11 @@ private static string PrivateImplementationInlineArrayGenericInstanceMethodFor(I return varName; } + + private static ITypeSymbol InlineArrayElementTypeFrom(ITypeSymbol inlineArrayType) + { + return ((IFieldSymbol) inlineArrayType.GetMembers().First()).Type; + } private static int InlineArrayLengthFrom(ITypeSymbol rhsType) {