Browse Source

Add support for decompiling fixed statements.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
db7653653d
  1. 15
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 4
      ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs
  3. 26
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  4. 35
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

15
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -176,6 +176,21 @@ namespace ICSharpCode.Decompiler.Ast @@ -176,6 +176,21 @@ namespace ICSharpCode.Decompiler.Ast
tryCatchStmt.CatchClauses.Add(cc);
}
yield return tryCatchStmt;
} else if (node is ILFixedStatement) {
ILFixedStatement fixedNode = (ILFixedStatement)node;
ILVariable v;
ILExpression init;
if (!fixedNode.Initializer.Match(ILCode.Stloc, out v, out init))
throw new InvalidOperationException("Fixed initializer must be an assignment to a local variable");
FixedStatement fixedStatement = new FixedStatement();
fixedStatement.Type = AstBuilder.ConvertType(v.Type);
fixedStatement.Variables.Add(
new VariableInitializer {
Name = v.Name,
Initializer = (Expression)TransformExpression(init)
}.WithAnnotation(v));
fixedStatement.EmbeddedStatement = TransformBlock(fixedNode.BodyBlock);
yield return fixedStatement;
} else if (node is ILBlock) {
yield return TransformBlock((ILBlock)node);
} else if (node is ILComment) {

4
ICSharpCode.Decompiler/Ast/DeclareVariableInSmallestScope.cs

@ -54,6 +54,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -54,6 +54,10 @@ namespace ICSharpCode.Decompiler.Ast
if (ident != null && ident.Identifier == name && ident.TypeArguments.Count == 0)
return node;
FixedStatement fixedStatement = node as FixedStatement;
if (fixedStatement != null && fixedStatement.Variables.Single().Name == name)
return null; // no need to introduce the variable here
AstNode withinCurrent = FindInsertPos(node.FirstChild, name, allowPassIntoLoops);
if (withinCurrent != null) {
if (pos == null) {

26
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -511,4 +511,30 @@ namespace ICSharpCode.Decompiler.ILAst @@ -511,4 +511,30 @@ namespace ICSharpCode.Decompiler.ILAst
output.WriteLine("}");
}
}
public class ILFixedStatement : ILNode
{
public ILExpression Initializer;
public ILBlock BodyBlock;
public override IEnumerable<ILNode> GetChildren()
{
if (this.Initializer != null)
yield return this.Initializer;
if (this.BodyBlock != null)
yield return this.BodyBlock;
}
public override void WriteTo(ITextOutput output)
{
output.Write("fixed (");
if (this.Initializer != null)
this.Initializer.WriteTo(output);
output.WriteLine(") {");
output.Indent();
this.BodyBlock.WriteTo(output);
output.Unindent();
output.WriteLine("}");
}
}
}

35
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -30,7 +30,8 @@ namespace ICSharpCode.Decompiler.ILAst @@ -30,7 +30,8 @@ namespace ICSharpCode.Decompiler.ILAst
initializerTransforms.TransformArrayInitializers,
initializerTransforms.TransformCollectionInitializers,
transforms.CachedDelegateInitialization,
transforms.MakeAssignmentExpression
transforms.MakeAssignmentExpression,
transforms.IntroduceFixedStatements
};
Func<ILExpression, ILExpression>[] exprTransforms = {
HandleDecimalConstants,
@ -292,5 +293,37 @@ namespace ICSharpCode.Decompiler.ILAst @@ -292,5 +293,37 @@ namespace ICSharpCode.Decompiler.ILAst
return false;
}
#endregion
#region IntroduceFixedStatements
void IntroduceFixedStatements(ILBlock block, ref int i)
{
// stloc(pinned_Var, conv.u(ldc.i4(0)))
ILExpression initValue;
ILVariable v;
if (!(block.Body[i].Match(ILCode.Stloc, out v, out initValue) && v.IsPinned))
return;
// find initialization of v:
int j;
for (j = i + 1; j < block.Body.Count; j++) {
ILVariable v2;
ILExpression storedVal;
if (block.Body[j].Match(ILCode.Stloc, out v2, out storedVal) && v2 == v) {
if (storedVal.Code == ILCode.Conv_U)
storedVal = storedVal.Arguments[0];
if (storedVal.Code == ILCode.Ldc_I4 && (int)storedVal.Operand == 0) {
// Create fixed statement from i to j
ILFixedStatement stmt = new ILFixedStatement();
stmt.Initializer = (ILExpression)block.Body[i];
stmt.BodyBlock = new ILBlock(block.Body.GetRange(i + 1, j - i - 1)); // from i+1 to j-1 (inclusive)
block.Body.RemoveRange(i + 1, j - i); // from j+1 to i (inclusive)
block.Body[i] = stmt;
if (v.Type.IsByReference)
v.Type = new PointerType(((ByReferenceType)v.Type).ElementType);
break;
}
}
}
}
#endregion
}
}

Loading…
Cancel
Save