Browse Source

Fix #2103: Support for `Stackalloc initializers` not working for `byte`

pull/2126/head
Siegfried Pammer 5 years ago
parent
commit
7ed4a736f3
  1. 30
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs
  2. 13
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  4. 27
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

30
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CS73_StackAllocInitializers.cs

@ -396,6 +396,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -396,6 +396,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return UseSpan(span);
}
public void Issue2103a()
{
Span<byte> span = stackalloc byte[3] {
1,
2,
3
};
Console.WriteLine(span[2] + span[0]);
}
public void Issue2103b()
{
Span<byte> span = stackalloc byte[3];
Console.WriteLine(span[0] + span[1]);
}
public void Issue2103c()
{
Console.WriteLine((stackalloc byte[3] {
1,
2,
3
})[2]);
}
public void Issue2103d()
{
Console.WriteLine((stackalloc byte[3])[1]);
}
public string UseSpan(Span<int> span)
{
throw new NotImplementedException();

13
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs

@ -189,10 +189,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -189,10 +189,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override void VisitIndexerExpression(IndexerExpression indexerExpression)
{
ParenthesizeIfRequired(indexerExpression.Target, PrecedenceLevel.Primary);
ArrayCreateExpression ace = indexerExpression.Target as ArrayCreateExpression;
if (ace != null && (InsertParenthesesForReadability || ace.Initializer.IsNull)) {
// require parentheses for "(new int[1])[0]"
Parenthesize(indexerExpression.Target);
switch (indexerExpression.Target) {
case ArrayCreateExpression ace when InsertParenthesesForReadability || ace.Initializer.IsNull:
// require parentheses for "(new int[1])[0]"
Parenthesize(indexerExpression.Target);
break;
case StackAllocExpression sae when InsertParenthesesForReadability || sae.Initializer.IsNull:
// require parentheses for "(stackalloc int[1])[0]"
Parenthesize(indexerExpression.Target);
break;
}
base.VisitIndexerExpression(indexerExpression);
}

2
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -408,7 +408,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -408,7 +408,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
var pointerType = new PointerType(elementType);
var elementCountInstr = PointerArithmeticOffset.Detect(sizeInBytesInstr, pointerType.ElementType, checkForOverflow: true, unwrapZeroExtension: true);
if (elementCountInstr == null || !elementCountInstr.Match(elementCountInstr2).Success)
if (elementCountInstr == null || !elementCountInstr.UnwrapConv(ConversionKind.ZeroExtend).Match(elementCountInstr2).Success)
return false;
return true;
}

27
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -227,17 +227,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -227,17 +227,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!dest.MatchLdLoc(v) || !src.MatchLdsFlda(out var field) || !size.MatchLdcI4((int)length))
return false;
if (field.MetadataToken.IsNil)
return false;
if (!block.Instructions[pos + 1].MatchStLoc(out var finalStore, out var value))
if (!(v.IsSingleDefinition && v.LoadCount == 2))
return false;
if (!value.MatchLdLoc(v))
if (field.MetadataToken.IsNil)
return false;
if (!block.Instructions[pos + 1].MatchStLoc(out var finalStore, out var value)) {
var otherLoadOfV = v.LoadInstructions.FirstOrDefault(l => !(l.Parent is Cpblk));
if (otherLoadOfV == null)
return false;
finalStore = otherLoadOfV.Parent.Extract();
value = ((StLoc)finalStore.StoreInstructions[0]).Value;
if (finalStore == null)
return false;
}
var fd = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA))
return false;
if (value.MatchLdLoc(v)) {
elementType = ((PointerType)finalStore.Type).ElementType;
} else if (value is NewObj { Arguments: { Count: 2 } } newObj
&& newObj.Method.DeclaringType.IsKnownType(KnownTypeCode.SpanOfT)
&& newObj.Arguments[0].MatchLdLoc(v)
&& newObj.Arguments[1].MatchLdcI4((int)length))
{
elementType = ((ParameterizedType)newObj.Method.DeclaringType).TypeArguments[0];
} else {
return false;
}
blob = fd.GetInitialValue(context.PEFile.Reader, context.TypeSystem);
elementType = ((PointerType)finalStore.Type).ElementType;
return true;
}

Loading…
Cancel
Save