Browse Source

TransformStackIntoVariables for TryCatch

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
f39b6f7672
  1. 16
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  2. 44
      ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

16
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -99,7 +99,8 @@ namespace ICSharpCode.Decompiler.CSharp
return new BreakStatement(); return new BreakStatement();
string label; string label;
if (!endContainerLabels.TryGetValue(inst.TargetContainer, out label)) { if (!endContainerLabels.TryGetValue(inst.TargetContainer, out label)) {
endContainerLabels.Add(inst.TargetContainer, "end_" + inst.TargetLabel); label = "end_" + inst.TargetLabel;
endContainerLabels.Add(inst.TargetContainer, label);
} }
return new GotoStatement(label); return new GotoStatement(label);
} }
@ -208,6 +209,10 @@ namespace ICSharpCode.Decompiler.CSharp
blockStatement.Add(new LabelStatement { Label = block.Label }); blockStatement.Add(new LabelStatement { Label = block.Label });
} }
foreach (var inst in block.Instructions) { foreach (var inst in block.Instructions) {
if (inst.OpCode == OpCode.Leave && IsFinalLeave((Leave)inst)) {
// skip the final 'leave' instruction and just fall out of the BlockStatement
continue;
}
blockStatement.Add(Convert(inst)); blockStatement.Add(Convert(inst));
} }
if (block.FinalInstruction.OpCode != OpCode.Nop) { if (block.FinalInstruction.OpCode != OpCode.Nop) {
@ -220,5 +225,14 @@ namespace ICSharpCode.Decompiler.CSharp
} }
return blockStatement; return blockStatement;
} }
static bool IsFinalLeave(Leave leave)
{
Block block = (Block)leave.Parent;
if (leave.ChildIndex != block.Instructions.Count - 1 || block.FinalInstruction.OpCode != OpCode.Nop)
return false;
BlockContainer container = (BlockContainer)block.Parent;
return block.ChildIndex == container.Blocks.Count - 1;
}
} }
} }

44
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

@ -118,7 +118,19 @@ namespace ICSharpCode.Decompiler.IL
internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state)
{ {
throw new NotImplementedException(); TryBlock = TryBlock.Inline(InstructionFlags.None, state);
TryBlock.TransformStackIntoVariables(state);
Stack<ILVariable> variablesAfter = TryBlock.HasFlag(InstructionFlags.EndPointUnreachable) ? null : state.Variables.Clone();
for (int i = 0; i < Handlers.Count; i++) {
Handlers[i].TransformStackIntoVariables(state);
if (!Handlers[i].HasFlag(InstructionFlags.EndPointUnreachable)) {
if (variablesAfter == null)
variablesAfter = state.Variables.Clone();
else
state.MergeVariables(variablesAfter, state.Variables);
}
}
state.Variables = variablesAfter ?? new Stack<ILVariable>();
} }
} }
@ -160,6 +172,12 @@ namespace ICSharpCode.Decompiler.IL
internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state)
{ {
state.Variables.Clear();
Filter = Filter.Inline(InstructionFlags.None, state);
Filter.TransformStackIntoVariables(state);
state.Variables.Clear();
Body = Body.Inline(InstructionFlags.None, state);
Body.TransformStackIntoVariables(state);
} }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
@ -266,7 +284,13 @@ namespace ICSharpCode.Decompiler.IL
internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state)
{ {
throw new NotImplementedException(); TryBlock = TryBlock.Inline(InstructionFlags.None, state);
TryBlock.TransformStackIntoVariables(state);
var variablesAfterTry = state.Variables;
state.Variables = new Stack<ILVariable>();
FinallyBlock = FinallyBlock.Inline(InstructionFlags.None, state);
FinallyBlock.TransformStackIntoVariables(state);
state.Variables = variablesAfterTry;
} }
} }
@ -344,7 +368,21 @@ namespace ICSharpCode.Decompiler.IL
internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state)
{ {
throw new NotImplementedException(); TryBlock = TryBlock.Inline(InstructionFlags.None, state);
TryBlock.TransformStackIntoVariables(state);
var variablesAfterTry = state.Variables;
state.Variables = new Stack<ILVariable>();
FaultBlock = FaultBlock.Inline(InstructionFlags.None, state);
FaultBlock.TransformStackIntoVariables(state);
if (!TryBlock.HasFlag(InstructionFlags.EndPointUnreachable) && !FaultBlock.HasFlag(InstructionFlags.EndPointUnreachable)) {
// If end-points of both instructions are reachable, merge their states
state.MergeVariables(state.Variables, variablesAfterTry);
}
if (FaultBlock.HasFlag(InstructionFlags.EndPointUnreachable)) {
// If the end-point of FaultBlock is unreachable, continue with the end-state of TryBlock instead
// (if both are unreachable, it doesn't matter what we continue with)
state.Variables = variablesAfterTry;
}
} }
} }
} }

Loading…
Cancel
Save