Skip to content

Commit

Permalink
adds test for accessing non zero index InlineArray element (#257)
Browse files Browse the repository at this point in the history
also fixes the reference to Unsafe.As<TBuffer, TElement>() and Unsafe.Add<TElement>(); the code was accessing the open generic methods, as opposed
to the generic instance methods.
  • Loading branch information
adrianoc committed Mar 27, 2024
1 parent 1e4aea5 commit ff32484
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 7 deletions.
38 changes: 36 additions & 2 deletions Cecilifier.Core.Tests/Tests/Unit/InlineArrayTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,41 @@ public struct IntBuffer { private int _element0; }
"""));
}

// Access to not first element
[TestCase("field[42] = 1", @"Ldflda, fld_field_\d+", TestName = "Field")]
[TestCase("parameter[42] = 1", @"Ldarga, p_parameter_\d+", TestName = "Parameter")]
[TestCase("local[42] = 1", @"Ldloca, l_local_\d+", TestName = "Local")]
public void AccessToNonFirstElement_Of_StorageLocation(string statement, string expectedOpCode)
{
var result = RunCecilifier($$"""
class C
{
public IntBuffer field;
void M(IntBuffer parameter)
{
var local = new IntBuffer();
{{statement}};
}
}
[System.Runtime.CompilerServices.InlineArray(100)]
public struct IntBuffer { private int _element0; }
""");

var cecilified = result.GeneratedCode.ReadToEnd();

Assert.That(cecilified, Does.Match($"""
(\s+il_M_\d+\.Emit\(OpCodes\.){expectedOpCode}\);
\1Ldc_I4, 42\);
\s+//\<PrivateImplementationDetails\> class.
"""));

Assert.That(cecilified, Does.Match("""
(\s+il_M_\d+\.Emit\(OpCodes\.)Call, gi_inlineArrayElementRef_\d+\);
\s+\1Ldc_I4, 1\);
\s+\1Stind_I4\);
"""));
}


// Element type: reference type, value type, custom value type
//ADD-ISSUE:
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,23 @@ public static string GetOrEmmitInlineArrayFirstElementRefMethod(IVisitorContext
return spanTypeParameter.MakeByReferenceType();
});

var tbufferTypeParameter = ResolveOwnedGenericParameter(context, "TBuffer", methodTypeQualifiedName);
var telementTypeParameter = ResolveOwnedGenericParameter(context, "TElement", methodTypeQualifiedName);

var unsafeAsVarName = context.Naming.SyntheticVariable("unsafeAs", ElementKind.GenericInstance);
var unsafeAsExps = GetUnsafeAsMethod(context)
.MethodResolverExpression(context)
.MakeGenericInstanceMethod(unsafeAsVarName, [tbufferTypeParameter, telementTypeParameter]);

var methodBodyExpressions = CecilDefinitionsFactory.MethodBody(
methodVar,
[
OpCodes.Ldarg_0,
OpCodes.Call.WithOperand(GetUnsafeAsMethod(context).MethodResolverExpression(context)),
OpCodes.Call.WithOperand(unsafeAsVarName),
OpCodes.Ret
]);

foreach (var exp in methodExpressions.Concat(methodBodyExpressions))
foreach (var exp in methodExpressions.Concat(unsafeAsExps).Concat(methodBodyExpressions))
{
context.WriteCecilExpression(exp);
context.WriteNewLine();
Expand Down Expand Up @@ -190,17 +198,30 @@ public static string GetOrEmmitInlineArrayElementRefMethod(IVisitorContext conte
return spanTypeParameter.MakeByReferenceType();
});

var tbufferTypeParameter = ResolveOwnedGenericParameter(context, "TBuffer", methodTypeQualifiedName);
var telementTypeParameter = ResolveOwnedGenericParameter(context, "TElement", methodTypeQualifiedName);

var unsafeAsVarName = context.Naming.SyntheticVariable("unsafeAs", ElementKind.GenericInstance);
var unsafeAsExps = GetUnsafeAsMethod(context)
.MethodResolverExpression(context)
.MakeGenericInstanceMethod(unsafeAsVarName, [tbufferTypeParameter, telementTypeParameter]);

var unsafeAddVarName = context.Naming.SyntheticVariable("unsafeAdd", ElementKind.GenericInstance);
var unsafeAddExps = GetUnsafeAddMethod(context)
.MethodResolverExpression(context)
.MakeGenericInstanceMethod(unsafeAddVarName, [telementTypeParameter]);

var methodBodyExpressions = CecilDefinitionsFactory.MethodBody(
methodVar,
[
OpCodes.Ldarg_0,
OpCodes.Call.WithOperand(GetUnsafeAsMethod(context).MethodResolverExpression(context)),
OpCodes.Call.WithOperand(unsafeAsVarName),
OpCodes.Ldarg_1,
OpCodes.Call.WithOperand(GetUnsafeAddMethod(context).MethodResolverExpression(context)),
OpCodes.Call.WithOperand(unsafeAddVarName),
OpCodes.Ret
]);

foreach (var exp in methodExpressions.Concat(methodBodyExpressions))
foreach (var exp in methodExpressions.Concat(unsafeAsExps).Concat(unsafeAddExps).Concat(methodBodyExpressions))
{
context.WriteCecilExpression(exp);
context.WriteNewLine();
Expand Down

0 comments on commit ff32484

Please sign in to comment.