Browse Source

Handle 'leave' instruction in StatementBuilder

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
3db0e01eee
  1. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 23
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  3. 5
      ICSharpCode.Decompiler/IL/Instructions/Block.cs

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -172,7 +172,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
return new TypeOfExpression(ConvertType(inst.Type)) return new TypeOfExpression(ConvertType(inst.Type))
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new TypeOfResolveResult(compilation.FindType(KnownTypeCode.Type), inst.Type); .WithRR(new TypeOfResolveResult(compilation.FindType(KnownTypeCode.Type), inst.Type));
} }
protected internal override TranslatedExpression VisitLogicNot(LogicNot inst) protected internal override TranslatedExpression VisitLogicNot(LogicNot inst)

23
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -88,6 +88,22 @@ namespace ICSharpCode.Decompiler.CSharp
return new GotoStatement(inst.TargetLabel); return new GotoStatement(inst.TargetLabel);
} }
/// <summary>Target container that a 'break;' statement would break out of</summary>
BlockContainer breakTarget;
/// <summary>Dictionary from BlockContainer to label name for 'goto of_container';</summary>
readonly Dictionary<BlockContainer, string> endContainerLabels = new Dictionary<BlockContainer, string>();
protected internal override Statement VisitLeave(Leave inst)
{
if (inst.TargetContainer == breakTarget)
return new BreakStatement();
string label;
if (!endContainerLabels.TryGetValue(inst.TargetContainer, out label)) {
endContainerLabels.Add(inst.TargetContainer, "end_" + inst.TargetLabel);
}
return new GotoStatement(label);
}
protected internal override Statement VisitThrow(Throw inst) protected internal override Statement VisitThrow(Throw inst)
{ {
return new ThrowStatement(exprBuilder.Translate(inst.Argument)); return new ThrowStatement(exprBuilder.Translate(inst.Argument));
@ -163,8 +179,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (container.EntryPoint.IncomingEdgeCount > 1) { if (container.EntryPoint.IncomingEdgeCount > 1) {
var oldContinueTarget = continueTarget; var oldContinueTarget = continueTarget;
var oldContinueCount = continueCount; var oldContinueCount = continueCount;
var oldBreakTarget = breakTarget;
continueTarget = container.EntryPoint; continueTarget = container.EntryPoint;
continueCount = 0; continueCount = 0;
breakTarget = container;
var blockStatement = ConvertBlockContainer(container); var blockStatement = ConvertBlockContainer(container);
Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount); Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount);
Debug.Assert(blockStatement.Statements.First() is LabelStatement); Debug.Assert(blockStatement.Statements.First() is LabelStatement);
@ -174,6 +192,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
continueTarget = oldContinueTarget; continueTarget = oldContinueTarget;
continueCount = oldContinueCount; continueCount = oldContinueCount;
breakTarget = oldBreakTarget;
return new WhileStatement(new PrimitiveExpression(true), blockStatement); return new WhileStatement(new PrimitiveExpression(true), blockStatement);
} else { } else {
return ConvertBlockContainer(container); return ConvertBlockContainer(container);
@ -195,6 +214,10 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Add(Convert(block.FinalInstruction)); blockStatement.Add(Convert(block.FinalInstruction));
} }
} }
string label;
if (endContainerLabels.TryGetValue(container, out label)) {
blockStatement.Add(new LabelStatement { Label = label });
}
return blockStatement; return blockStatement;
} }
} }

5
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -51,8 +51,9 @@ namespace ICSharpCode.Decompiler.IL
/// </para> /// </para>
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Fun fact: the empty block acts like a phase-2 pop instruction, /// Fun fact: wrapping a pop instruction in a block
/// which is a slightly different behavior than the normal phase-1 <see cref="Pop"/> instruction! /// (<c>new Block { FinalInstruction = popInst }</c>) turns it
/// from a phase-1 pop instruction to a phase-2 pop instruction.
/// However, this is just of theoretical interest; we currently don't plan to use inline blocks that /// However, this is just of theoretical interest; we currently don't plan to use inline blocks that
/// pop elements that they didn't push themselves. /// pop elements that they didn't push themselves.
/// </remarks> /// </remarks>

Loading…
Cancel
Save