Browse Source

Merge pull request #1505 from icsharpcode/fixed-buffers

Fixed buffers enhancements
pull/1515/head
Siegfried Pammer 6 years ago committed by GitHub
parent
commit
a64f22abd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  2. 21
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 16
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  4. 8
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  5. 8
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  6. 26
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  7. 15
      ILSpy/Languages/CSharpHighlightingTokenWriter.cs

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -439,5 +439,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -439,5 +439,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return CreateBuffer(array2.Length, ptr2);
}
}
private unsafe static void Issue1499(StructWithFixedSizeMembers value, int index)
{
int num = value.Integers[index];
num.ToString();
}
}
}

21
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1406,6 +1406,27 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1406,6 +1406,27 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
internal static bool IsFixedField(MetadataReader metadata, FieldDefinitionHandle handle, out IType type, out int elementCount)
{
type = null;
elementCount = 0;
var field = metadata.GetFieldDefinition(handle);
foreach (var h in field.GetCustomAttributes()) {
var customAttribute = metadata.GetCustomAttribute(h);
if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.FixedBuffer)) {
var value = customAttribute.DecodeValue(MetadataExtensions.minimalCorlibTypeProvider);
if (value.FixedArguments.Length == 2) {
if (value.FixedArguments[0].Value is IType trr && value.FixedArguments[1].Value is int length) {
type = trr;
elementCount = length;
return true;
}
}
}
}
return false;
}
EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == property);

16
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1024,6 +1024,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1024,6 +1024,19 @@ namespace ICSharpCode.Decompiler.CSharp
string name = (inst.Operator == BinaryNumericOperator.Sub ? "Subtract" : "Add");
ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Right, brt.ElementType, inst.CheckForOverflow);
if (offsetInst != null) {
if (settings.FixedBuffers && inst.Operator == BinaryNumericOperator.Add && inst.Left is LdFlda ldFlda
&& ldFlda.Target is LdFlda nestedLdFlda && CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _)) {
Expression fieldAccess = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target);
var mrr = (MemberResolveResult)fieldAccess.GetResolveResult();
fieldAccess.RemoveAnnotations<ResolveResult>();
var result = fieldAccess.WithRR(new MemberResolveResult(mrr.TargetResult, mrr.Member, new PointerType(elementType)))
.WithILInstruction(inst);
TranslatedExpression expr = new IndexerExpression(result.Expression, Translate(offsetInst).Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(elementType));
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, isOut: false));
}
return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst);
} else {
return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst);
@ -1985,8 +1998,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1985,8 +1998,9 @@ namespace ICSharpCode.Decompiler.CSharp
&& CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _))
{
Expression fieldAccess = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target);
var mrr = (MemberResolveResult)fieldAccess.GetResolveResult();
fieldAccess.RemoveAnnotations<ResolveResult>();
var result = fieldAccess.WithRR(new ResolveResult(new PointerType(elementType)))
var result = fieldAccess.WithRR(new MemberResolveResult(mrr.TargetResult, mrr.Member, new PointerType(elementType)))
.WithILInstruction(inst);
if (inst.ResultType == StackType.Ref) {
// convert pointer back to ref

8
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -137,7 +137,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -137,7 +137,13 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
writer.Space();
writer.WriteToken(Roles.Colon, ":");
writer.Space();
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
if (symbol is IField f && CSharpDecompiler.IsFixedField(f.ParentModule.PEFile.Metadata, (System.Reflection.Metadata.FieldDefinitionHandle)f.MetadataToken, out var type, out int elementCount)) {
rt = astBuilder.ConvertType(type);
new IndexerExpression(new TypeReferenceExpression(rt), astBuilder.ConvertConstantValue(f.Compilation.FindType(KnownTypeCode.Int32), elementCount))
.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
} else {
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}
}
}

8
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -176,25 +176,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -176,25 +176,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool UseCustomEvents { get; set; }
/// <summary>
/// Controls if unbound type argument names are inserted in the ast or not.
/// Controls whether unbound type argument names are inserted in the ast or not.
/// The default value is <c>false</c>.
/// </summary>
public bool ConvertUnboundTypeArguments { get; set;}
/// <summary>
/// Controls if aliases should be used inside the type name or not.
/// Controls whether aliases should be used inside the type name or not.
/// The default value is <c>true</c>.
/// </summary>
public bool UseAliases { get; set; }
/// <summary>
/// Controls if constants like <c>int.MaxValue</c> are converted to a <see cref="MemberReferenceExpression"/> or <see cref="PrimitiveExpression" />.
/// Controls whether constants like <c>int.MaxValue</c> are converted to a <see cref="MemberReferenceExpression"/> or <see cref="PrimitiveExpression" />.
/// The default value is <c>true</c>.
/// </summary>
public bool UseSpecialConstants { get; set; }
/// <summary>
/// Controls if integral constants should be printed in hexadecimal format.
/// Controls whether integral constants should be printed in hexadecimal format.
/// The default value is <c>false</c>.
/// </summary>
public bool PrintIntegralValuesAsHex { get; set; }

26
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -401,29 +401,9 @@ namespace ICSharpCode.Decompiler @@ -401,29 +401,9 @@ namespace ICSharpCode.Decompiler
{
if (nodeStack.Pop() != node)
throw new InvalidOperationException();
// var startLocation = startLocations.Pop();
//
// // code mappings
// var ranges = node.Annotation<List<ILRange>>();
// if (symbolsStack.Count > 0 && ranges != null && ranges.Count > 0) {
// // Ignore the newline which was printed at the end of the statement
// TextLocation endLocation = (node is Statement) ? (lastEndOfLine ?? output.Location) : output.Location;
// symbolsStack.Peek().SequencePoints.Add(
// new SequencePoint() {
// ILRanges = ILRange.OrderAndJoin(ranges).ToArray(),
// StartLocation = startLocation,
// EndLocation = endLocation
// });
// }
//
// if (node.Annotation<MethodDebugSymbols>() != null) {
// symbolsStack.Peek().EndLocation = output.Location;
// output.AddDebugSymbols(symbolsStack.Pop());
// }
}
static bool IsDefinition(ref AstNode node)
public static bool IsDefinition(ref AstNode node)
{
if (node is EntityDeclaration)
return true;
@ -431,8 +411,10 @@ namespace ICSharpCode.Decompiler @@ -431,8 +411,10 @@ namespace ICSharpCode.Decompiler
node = node.Parent;
return true;
}
if (node is FixedVariableInitializer)
if (node is FixedVariableInitializer && node.Parent is FixedFieldDeclaration) {
node = node.Parent;
return true;
}
return false;
}
}

15
ILSpy/Languages/CSharpHighlightingTokenWriter.cs

@ -385,25 +385,12 @@ namespace ICSharpCode.ILSpy @@ -385,25 +385,12 @@ namespace ICSharpCode.ILSpy
var node = nodeStack.Peek();
if (node is Identifier)
node = node.Parent;
if (IsDefinition(ref node))
if (Decompiler.TextTokenWriter.IsDefinition(ref node))
return node.GetSymbol();
return null;
}
static bool IsDefinition(ref AstNode node)
{
if (node is EntityDeclaration)
return true;
if (node is VariableInitializer && node.Parent is FieldDeclaration) {
node = node.Parent;
return true;
}
if (node is FixedVariableInitializer)
return true;
return false;
}
ISymbol GetCurrentMemberReference()
{
AstNode node = nodeStack.Peek();

Loading…
Cancel
Save