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. 6
      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
return CreateBuffer(array2.Length, ptr2); 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
return false; 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) EntityDeclaration DoDecompile(IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == property); Debug.Assert(decompilationContext.CurrentMember == property);

16
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1024,6 +1024,19 @@ namespace ICSharpCode.Decompiler.CSharp
string name = (inst.Operator == BinaryNumericOperator.Sub ? "Subtract" : "Add"); string name = (inst.Operator == BinaryNumericOperator.Sub ? "Subtract" : "Add");
ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Right, brt.ElementType, inst.CheckForOverflow); ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Right, brt.ElementType, inst.CheckForOverflow);
if (offsetInst != null) { 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); return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst);
} else { } else {
return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst); return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst);
@ -1985,8 +1998,9 @@ namespace ICSharpCode.Decompiler.CSharp
&& CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _)) && CSharpDecompiler.IsFixedField(nestedLdFlda.Field, out var elementType, out _))
{ {
Expression fieldAccess = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target); Expression fieldAccess = ConvertField(nestedLdFlda.Field, nestedLdFlda.Target);
var mrr = (MemberResolveResult)fieldAccess.GetResolveResult();
fieldAccess.RemoveAnnotations<ResolveResult>(); 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); .WithILInstruction(inst);
if (inst.ResultType == StackType.Ref) { if (inst.ResultType == StackType.Ref) {
// convert pointer back to ref // convert pointer back to ref

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

@ -137,9 +137,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
writer.Space(); writer.Space();
writer.WriteToken(Roles.Colon, ":"); writer.WriteToken(Roles.Colon, ":");
writer.Space(); writer.Space();
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)); rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
} }
} }
}
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) { if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) {
IProperty property = symbol as IProperty; IProperty property = symbol as IProperty;

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

@ -176,25 +176,25 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool UseCustomEvents { get; set; } public bool UseCustomEvents { get; set; }
/// <summary> /// <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>. /// The default value is <c>false</c>.
/// </summary> /// </summary>
public bool ConvertUnboundTypeArguments { get; set;} public bool ConvertUnboundTypeArguments { get; set;}
/// <summary> /// <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>. /// The default value is <c>true</c>.
/// </summary> /// </summary>
public bool UseAliases { get; set; } public bool UseAliases { get; set; }
/// <summary> /// <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>. /// The default value is <c>true</c>.
/// </summary> /// </summary>
public bool UseSpecialConstants { get; set; } public bool UseSpecialConstants { get; set; }
/// <summary> /// <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>. /// The default value is <c>false</c>.
/// </summary> /// </summary>
public bool PrintIntegralValuesAsHex { get; set; } public bool PrintIntegralValuesAsHex { get; set; }

26
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -401,29 +401,9 @@ namespace ICSharpCode.Decompiler
{ {
if (nodeStack.Pop() != node) if (nodeStack.Pop() != node)
throw new InvalidOperationException(); 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) if (node is EntityDeclaration)
return true; return true;
@ -431,8 +411,10 @@ namespace ICSharpCode.Decompiler
node = node.Parent; node = node.Parent;
return true; return true;
} }
if (node is FixedVariableInitializer) if (node is FixedVariableInitializer && node.Parent is FixedFieldDeclaration) {
node = node.Parent;
return true; return true;
}
return false; return false;
} }
} }

15
ILSpy/Languages/CSharpHighlightingTokenWriter.cs

@ -385,25 +385,12 @@ namespace ICSharpCode.ILSpy
var node = nodeStack.Peek(); var node = nodeStack.Peek();
if (node is Identifier) if (node is Identifier)
node = node.Parent; node = node.Parent;
if (IsDefinition(ref node)) if (Decompiler.TextTokenWriter.IsDefinition(ref node))
return node.GetSymbol(); return node.GetSymbol();
return null; 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() ISymbol GetCurrentMemberReference()
{ {
AstNode node = nodeStack.Peek(); AstNode node = nodeStack.Peek();

Loading…
Cancel
Save