Browse Source

Improve SequencePointBuilder

pull/923/head
Siegfried Pammer 8 years ago
parent
commit
4ca4d97011
  1. 14
      ICSharpCode.Decompiler/CSharp/Annotations.cs
  2. 14
      ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs
  4. 32
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  5. 1
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  6. 4
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  7. 20
      ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs
  8. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  9. 11
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  10. 3
      ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs
  11. 6
      ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs

14
ICSharpCode.Decompiler/CSharp/Annotations.cs

@ -164,4 +164,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -164,4 +164,18 @@ namespace ICSharpCode.Decompiler.CSharp
this.Variable = v;
}
}
public class ForeachAnnotation
{
public readonly ILInstruction GetEnumeratorCall;
public readonly ILInstruction MoveNextCall;
public readonly ILInstruction GetCurrentCall;
public ForeachAnnotation(ILInstruction getEnumeratorCall, ILInstruction moveNextCall, ILInstruction getCurrentCall)
{
GetEnumeratorCall = getEnumeratorCall;
MoveNextCall = moveNextCall;
GetCurrentCall = getCurrentCall;
}
}
}

14
ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs

@ -17,8 +17,10 @@ @@ -17,8 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.CSharp
{
@ -31,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -31,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp
node.AddAnnotation(annotation);
return node;
}
public static T CopyAnnotationsFrom<T>(this T node, AstNode other) where T : AstNode
{
foreach (object annotation in other.Annotations) {
@ -39,7 +41,15 @@ namespace ICSharpCode.Decompiler.CSharp @@ -39,7 +41,15 @@ namespace ICSharpCode.Decompiler.CSharp
}
return node;
}
public static T CopyInstructionsFrom<T>(this T node, AstNode other) where T : AstNode
{
foreach (object annotation in other.Annotations.OfType<ILInstruction>()) {
node.AddAnnotation(annotation);
}
return node;
}
public static T Detach<T>(this T node) where T : AstNode
{
node.Remove();

5
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs

@ -88,7 +88,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -88,7 +88,10 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (node != null)
node.Location = start;
}
if (t != null) currentList.Add(t);
if (t != null) {
currentList.Add(t);
t.Role = role;
}
base.WriteKeyword(role, keyword);
}

32
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -135,6 +135,36 @@ namespace ICSharpCode.Decompiler.CSharp @@ -135,6 +135,36 @@ namespace ICSharpCode.Decompiler.CSharp
EndSequencePoint(usingStatement.StartLocation, usingStatement.RParToken.EndLocation);
}
public override void VisitForeachStatement(ForeachStatement foreachStatement)
{
var foreachInfo = foreachStatement.Annotation<ForeachAnnotation>();
if (foreachInfo == null) {
base.VisitForeachStatement(foreachStatement);
return;
}
// TODO : Add a sequence point on foreach token (mapped to nop before using instruction).
StartSequencePoint(foreachStatement);
foreachStatement.InExpression.AcceptVisitor(this);
AddToSequencePoint(foreachInfo.GetEnumeratorCall);
EndSequencePoint(foreachStatement.InExpression.StartLocation, foreachStatement.InExpression.EndLocation);
StartSequencePoint(foreachStatement);
AddToSequencePoint(foreachInfo.MoveNextCall);
EndSequencePoint(foreachStatement.InToken.StartLocation, foreachStatement.InToken.EndLocation);
StartSequencePoint(foreachStatement);
AddToSequencePoint(foreachInfo.GetCurrentCall);
EndSequencePoint(foreachStatement.VariableType.StartLocation, foreachStatement.VariableNameToken.EndLocation);
VisitAsSequencePoint(foreachStatement.EmbeddedStatement);
}
public override void VisitLockStatement(LockStatement lockStatement)
{
StartSequencePoint(lockStatement);
lockStatement.Expression.AcceptVisitor(this);
VisitAsSequencePoint(lockStatement.EmbeddedStatement);
AddToSequencePoint(lockStatement);
EndSequencePoint(lockStatement.StartLocation, lockStatement.RParToken.EndLocation);
}
/// <summary>
/// Start a new C# statement = new sequence point.
/// </summary>
@ -146,6 +176,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -146,6 +176,8 @@ namespace ICSharpCode.Decompiler.CSharp
void EndSequencePoint(TextLocation startLocation, TextLocation endLocation)
{
Debug.Assert(!startLocation.IsEmpty, "missing startLocation");
Debug.Assert(!endLocation.IsEmpty, "missing endLocation");
if (current.Intervals.Count > 0 && current.Function != null) {
// use LongSet to deduplicate and merge the intervals
var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End)));

1
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -506,6 +506,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -506,6 +506,7 @@ namespace ICSharpCode.Decompiler.CSharp
};
// Add the variable annotation for highlighting (TokenTextWriter expects it directly on the ForeachStatement).
foreachStmt.AddAnnotation(new ILVariableResolveResult(foreachVariable, foreachVariable.Type));
foreachStmt.AddAnnotation(new ForeachAnnotation(inst.ResourceExpression, loop.Conditions.Single(), singleGetter));
// If there was an optional return statement, return it as well.
if (optionalReturnAfterLoop != null) {
return new BlockStatement {

4
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -69,7 +69,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -69,7 +69,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
case "System.Type.GetTypeFromHandle":
if (arguments.Length == 1) {
if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) {
invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target);
Expression target = ((MemberReferenceExpression)arguments[0]).Target;
target.CopyInstructionsFrom(invocationExpression);
invocationExpression.ReplaceWith(target);
return;
}
}

20
ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs

@ -44,9 +44,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -44,9 +44,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var block in function.Descendants.OfType<Block>()) {
context.CancellationToken.ThrowIfCancellationRequested();
// Remove 'nop' instructions
block.Instructions.RemoveAll(inst => inst.OpCode == OpCode.Nop);
RemoveNopInstructions(block);
InlineVariableInReturnBlock(block, context);
// 1st pass SimplifySwitchInstruction before SimplifyBranchChains()
// starts duplicating return instructions.
@ -55,7 +54,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -55,7 +54,20 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
SimplifyBranchChains(function, context);
CleanUpEmptyBlocks(function, context);
}
private static void RemoveNopInstructions(Block block)
{
// Move ILRanges of special nop instructions to the previous non-nop instruction.
for (int i = block.Instructions.Count - 1; i > 0; i--) {
if (block.Instructions[i] is Nop nop && nop.Kind == NopKind.Pop) {
block.Instructions[i - 1].AddILRange(nop.ILRange);
}
}
// Remove 'nop' instructions
block.Instructions.RemoveAll(inst => inst.OpCode == OpCode.Nop);
}
void InlineVariableInReturnBlock(Block block, ILTransformContext context)
{
// In debug mode, the C#-compiler generates 'return blocks' that

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -650,7 +650,7 @@ namespace ICSharpCode.Decompiler.IL @@ -650,7 +650,7 @@ namespace ICSharpCode.Decompiler.IL
return BinaryNumeric(BinaryNumericOperator.BitOr);
case Cil.Code.Pop:
Pop();
return new Nop();
return new Nop() { Kind = NopKind.Pop };
case Cil.Code.Rem:
return BinaryNumeric(BinaryNumericOperator.Rem, false, Sign.Signed);
case Cil.Code.Rem_Un:

11
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs

@ -31,15 +31,26 @@ namespace ICSharpCode.Decompiler.IL @@ -31,15 +31,26 @@ namespace ICSharpCode.Decompiler.IL
// the non-custom WriteTo would add useless parentheses
}
}
public enum NopKind
{
Normal,
Pop
}
partial class Nop
{
public string Comment;
public NopKind Kind;
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
if (Kind != NopKind.Normal) {
output.Write("." + Kind.ToString().ToLowerInvariant());
}
if (!string.IsNullOrEmpty(Comment)) {
output.Write(" // " + Comment);
}

3
ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs

@ -51,9 +51,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -51,9 +51,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// dead store to stack
if (copiedExpr.Flags == InstructionFlags.None) {
// no-op -> delete
context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i - 1]);
block.Instructions.RemoveAt(i--);
} else {
// evaluate the value for its side-effects
context.Step("remove dead store to stack: evaluate the value for its side-effects", block.Instructions[i]);
copiedExpr.AddILRange(block.Instructions[i].ILRange);
block.Instructions[i] = copiedExpr;
}
} else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) {

6
ICSharpCode.Decompiler/IL/Transforms/LockTransform.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -83,7 +83,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.Step("LockTransformV2", block);
block.Instructions.RemoveAt(i - 1);
block.Instructions.RemoveAt(i - 2);
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock));
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange });
return true;
}
@ -127,7 +127,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -127,7 +127,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.Step("LockTransformV4", block);
block.Instructions.RemoveAt(i - 1);
tryContainer.EntryPoint.Instructions.RemoveAt(0);
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock));
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange });
return true;
}
@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -173,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.Instructions.RemoveAt(i - 1);
block.Instructions.RemoveAt(i - 2);
tryContainer.EntryPoint.Instructions.RemoveAt(0);
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock));
body.ReplaceWith(new LockInstruction(objectStore.Value, body.TryBlock) { ILRange = objectStore.ILRange });
return true;
}

Loading…
Cancel
Save