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. 9
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertParenthesesVisitor.cs
  3. 2
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  4. 23
      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
return UseSpan(span); 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) public string UseSpan(Span<int> span)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

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

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

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

@ -408,7 +408,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
var pointerType = new PointerType(elementType); var pointerType = new PointerType(elementType);
var elementCountInstr = PointerArithmeticOffset.Detect(sizeInBytesInstr, pointerType.ElementType, checkForOverflow: true, unwrapZeroExtension: true); 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 false;
return true; return true;
} }

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

@ -227,17 +227,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false; return false;
if (!dest.MatchLdLoc(v) || !src.MatchLdsFlda(out var field) || !size.MatchLdcI4((int)length)) if (!dest.MatchLdLoc(v) || !src.MatchLdsFlda(out var field) || !size.MatchLdcI4((int)length))
return false; return false;
if (!(v.IsSingleDefinition && v.LoadCount == 2))
return false;
if (field.MetadataToken.IsNil) if (field.MetadataToken.IsNil)
return false; return false;
if (!block.Instructions[pos + 1].MatchStLoc(out var finalStore, out var value)) 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; return false;
if (!value.MatchLdLoc(v)) finalStore = otherLoadOfV.Parent.Extract();
value = ((StLoc)finalStore.StoreInstructions[0]).Value;
if (finalStore == null)
return false; return false;
}
var fd = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken); var fd = context.PEFile.Metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA)) if (!fd.HasFlag(System.Reflection.FieldAttributes.HasFieldRVA))
return false; return false;
blob = fd.GetInitialValue(context.PEFile.Reader, context.TypeSystem); if (value.MatchLdLoc(v)) {
elementType = ((PointerType)finalStore.Type).ElementType; 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);
return true; return true;
} }

Loading…
Cancel
Save