Browse Source

Fix building TryCatchHandlers

pull/728/head
Daniel Grunwald 10 years ago
parent
commit
1e2147d1bd
  1. 15
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  2. 11
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 2
      NRefactory

15
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -31,6 +31,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
readonly Mono.Cecil.Cil.MethodBody body; readonly Mono.Cecil.Cil.MethodBody body;
readonly IDecompilerTypeSystem typeSystem; readonly IDecompilerTypeSystem typeSystem;
readonly Dictionary<Mono.Cecil.Cil.ExceptionHandler, ILVariable> variableByExceptionHandler;
/// <summary> /// <summary>
/// Gets/Sets whether to create extended basic blocks instead of basic blocks. /// Gets/Sets whether to create extended basic blocks instead of basic blocks.
@ -38,12 +39,15 @@ namespace ICSharpCode.Decompiler.IL
/// </summary> /// </summary>
public bool CreateExtendedBlocks; public bool CreateExtendedBlocks;
public BlockBuilder(Mono.Cecil.Cil.MethodBody body, IDecompilerTypeSystem typeSystem) internal BlockBuilder(Mono.Cecil.Cil.MethodBody body, IDecompilerTypeSystem typeSystem,
Dictionary<Mono.Cecil.Cil.ExceptionHandler, ILVariable> variableByExceptionHandler)
{ {
Debug.Assert(body != null); Debug.Assert(body != null);
Debug.Assert(typeSystem != null); Debug.Assert(typeSystem != null);
Debug.Assert(variableByExceptionHandler != null);
this.body = body; this.body = body;
this.typeSystem = typeSystem; this.typeSystem = typeSystem;
this.variableByExceptionHandler = variableByExceptionHandler;
} }
List<TryInstruction> tryInstructionList = new List<TryInstruction>(); List<TryInstruction> tryInstructionList = new List<TryInstruction>();
@ -78,25 +82,18 @@ namespace ICSharpCode.Decompiler.IL
tryInstructionList.Add(tryCatch); tryInstructionList.Add(tryCatch);
} }
ILVariable variable = null;
throw new NotImplementedException();
//var variable = new ILVariable(VariableKind.Exception, typeSystem.Resolve(eh.CatchType), handlerBlock.ILRange.Start);
variable.Name = "ex";
handlerBlock.EntryPoint.Instructions.Add(new LdLoc(variable));
ILInstruction filter; ILInstruction filter;
if (eh.HandlerType == Mono.Cecil.Cil.ExceptionHandlerType.Filter) { if (eh.HandlerType == Mono.Cecil.Cil.ExceptionHandlerType.Filter) {
var filterBlock = new BlockContainer(); var filterBlock = new BlockContainer();
filterBlock.ILRange = new Interval(eh.FilterStart.Offset, eh.HandlerStart.Offset); filterBlock.ILRange = new Interval(eh.FilterStart.Offset, eh.HandlerStart.Offset);
filterBlock.Blocks.Add(new Block()); filterBlock.Blocks.Add(new Block());
filterBlock.EntryPoint.Instructions.Add(new LdLoc(variable));
handlerContainers.Add(filterBlock.ILRange.Start, filterBlock); handlerContainers.Add(filterBlock.ILRange.Start, filterBlock);
filter = filterBlock; filter = filterBlock;
} else { } else {
filter = new LdcI4(1); filter = new LdcI4(1);
} }
tryCatch.Handlers.Add(new TryCatchHandler(filter, handlerBlock, variable)); tryCatch.Handlers.Add(new TryCatchHandler(filter, handlerBlock, variableByExceptionHandler[eh]));
} }
if (tryInstructionList.Count > 0) { if (tryInstructionList.Count > 0) {
tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.ILRange.Start).ThenByDescending(tc => tc.TryBlock.ILRange.End).ToList(); tryInstructionList = tryInstructionList.OrderBy(tc => tc.TryBlock.ILRange.Start).ThenByDescending(tc => tc.TryBlock.ILRange.End).ToList();

11
ICSharpCode.Decompiler/IL/ILReader.cs

@ -68,6 +68,7 @@ namespace ICSharpCode.Decompiler.IL
// Dictionary that stores stacks for each IL instruction // Dictionary that stores stacks for each IL instruction
Dictionary<int, ImmutableStack<ILVariable>> stackByOffset; Dictionary<int, ImmutableStack<ILVariable>> stackByOffset;
Dictionary<Cil.ExceptionHandler, ILVariable> variableByExceptionHandler;
UnionFind<ILVariable> unionFind; UnionFind<ILVariable> unionFind;
IEnumerable<ILVariable> stackVariables; IEnumerable<ILVariable> stackVariables;
@ -84,6 +85,7 @@ namespace ICSharpCode.Decompiler.IL
this.instructionBuilder = new List<ILInstruction>(); this.instructionBuilder = new List<ILInstruction>();
this.isBranchTarget = new BitArray(body.CodeSize); this.isBranchTarget = new BitArray(body.CodeSize);
this.stackByOffset = new Dictionary<int, ImmutableStack<ILVariable>>(); this.stackByOffset = new Dictionary<int, ImmutableStack<ILVariable>>();
this.variableByExceptionHandler = new Dictionary<Cil.ExceptionHandler, ILVariable>();
} }
IMetadataTokenProvider ReadAndDecodeMetadataToken() IMetadataTokenProvider ReadAndDecodeMetadataToken()
@ -160,6 +162,7 @@ namespace ICSharpCode.Decompiler.IL
void MergeStacks(ImmutableStack<ILVariable> a, ImmutableStack<ILVariable> b) void MergeStacks(ImmutableStack<ILVariable> a, ImmutableStack<ILVariable> b)
{ {
Debug.Assert(a.Count() == b.Count());
var enum1 = a.GetEnumerator(); var enum1 = a.GetEnumerator();
var enum2 = b.GetEnumerator(); var enum2 = b.GetEnumerator();
while (enum1.MoveNext() && enum2.MoveNext()) { while (enum1.MoveNext() && enum2.MoveNext()) {
@ -183,9 +186,9 @@ namespace ICSharpCode.Decompiler.IL
foreach (var eh in body.ExceptionHandlers) { foreach (var eh in body.ExceptionHandlers) {
ImmutableStack<ILVariable> ehStack = null; ImmutableStack<ILVariable> ehStack = null;
if (eh.HandlerType == Cil.ExceptionHandlerType.Catch || eh.HandlerType == Cil.ExceptionHandlerType.Filter) { if (eh.HandlerType == Cil.ExceptionHandlerType.Catch || eh.HandlerType == Cil.ExceptionHandlerType.Filter) {
ehStack = ImmutableStack.Create( var v = new ILVariable(VariableKind.Exception, typeSystem.Resolve(eh.CatchType), eh.HandlerStart.Offset);
new ILVariable(VariableKind.Exception, typeSystem.Resolve(eh.CatchType), eh.HandlerStart.Offset) variableByExceptionHandler.Add(eh, v);
); ehStack = ImmutableStack.Create(v);
} else { } else {
ehStack = ImmutableStack<ILVariable>.Empty; ehStack = ImmutableStack<ILVariable>.Empty;
} }
@ -262,7 +265,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
Init(body); Init(body);
ReadInstructions(cancellationToken); ReadInstructions(cancellationToken);
var container = new BlockBuilder(body, typeSystem).CreateBlocks(instructionBuilder, isBranchTarget); var container = new BlockBuilder(body, typeSystem, variableByExceptionHandler).CreateBlocks(instructionBuilder, isBranchTarget);
var function = new ILFunction(body.Method, container); var function = new ILFunction(body.Method, container);
function.Variables.AddRange(parameterVariables); function.Variables.AddRange(parameterVariables);
function.Variables.AddRange(localVariables); function.Variables.AddRange(localVariables);

2
NRefactory

@ -1 +1 @@
Subproject commit 3af570c381d98b9560f38058c728e0a97d918b07 Subproject commit 6e6d7778883fb135a0b6945cc4696c176b9c5e3a
Loading…
Cancel
Save