Browse Source

Add some basic expressions to ExpressionBuilder.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
f0b58d9701
  1. 8
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 23
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs
  4. 38
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  5. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  6. 10
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  7. 6
      ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs

8
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp
typeSystemAstBuilder.AlwaysUseShortTypeNames = true; typeSystemAstBuilder.AlwaysUseShortTypeNames = true;
typeSystemAstBuilder.AddAnnotations = true; typeSystemAstBuilder.AddAnnotations = true;
statementBuilder = new StatementBuilder(); statementBuilder = new StatementBuilder(compilation);
} }
MemberReference GetMemberReference(IMember member) MemberReference GetMemberReference(IMember member)
@ -84,9 +84,9 @@ namespace ICSharpCode.Decompiler.CSharp
if (methodDefinition.HasBody) { if (methodDefinition.HasBody) {
var ilReader = new ILReader(methodDefinition.Body, CancellationToken); var ilReader = new ILReader(methodDefinition.Body, CancellationToken);
var inst = ilReader.CreateBlocks(true); var inst = ilReader.CreateBlocks(true);
var body = statementBuilder.Convert(inst); var body = statementBuilder.ConvertBlockContainer(inst);
var bodyBlock = body as BlockStatement ?? new BlockStatement { body }; body.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
entityDecl.AddChild(bodyBlock, Roles.Body); entityDecl.AddChild(body, Roles.Body);
} }
return entityDecl; return entityDecl;
} }

23
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -12,7 +12,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary> /// <summary>
/// Translates from ILAst to C# expressions. /// Translates from ILAst to C# expressions.
/// </summary> /// </summary>
class ExpressionBuilder class ExpressionBuilder(private readonly ICompilation compilation)
{ {
struct ConvertedExpression(public readonly Expression Expression, public readonly IType Type) { } struct ConvertedExpression(public readonly Expression Expression, public readonly IType Type) { }
@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.CSharp
expr.AddAnnotation(inst); expr.AddAnnotation(inst);
return expr; return expr;
} }
ConvertedExpression ConvertArgument(ILInstruction inst) ConvertedExpression ConvertArgument(ILInstruction inst)
{ {
var cexpr = TransformExpression(inst); var cexpr = TransformExpression(inst);
@ -33,6 +33,14 @@ namespace ICSharpCode.Decompiler.CSharp
ConvertedExpression TransformExpression(ILInstruction inst) ConvertedExpression TransformExpression(ILInstruction inst)
{ {
switch (inst.OpCode) { switch (inst.OpCode) {
case OpCode.LdcI4:
return new ConvertedExpression(
new PrimitiveExpression(((ConstantI4)inst).Value),
compilation.FindType(KnownTypeCode.Int32));
case OpCode.LogicNot:
return new ConvertedExpression(
new UnaryOperatorExpression(UnaryOperatorType.Not, ConvertCondition(((LogicNotInstruction)inst).Operand)),
compilation.FindType(KnownTypeCode.Boolean));
default: default:
return ErrorExpression("OpCode not supported: " + inst.OpCode); return ErrorExpression("OpCode not supported: " + inst.OpCode);
} }
@ -44,5 +52,16 @@ namespace ICSharpCode.Decompiler.CSharp
e.AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment); e.AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment);
return new ConvertedExpression(e, SpecialType.UnknownType); return new ConvertedExpression(e, SpecialType.UnknownType);
} }
public Expression ConvertCondition(ILInstruction condition)
{
var expr = ConvertArgument(condition);
if (expr.Type.IsKnownType(KnownTypeCode.Boolean) || expr.Type.Kind == TypeKind.Unknown)
return expr.Expression;
else if (expr.Type.Kind == TypeKind.Pointer)
return new BinaryOperatorExpression(expr.Expression, BinaryOperatorType.InEquality, new NullReferenceExpression());
else
return new BinaryOperatorExpression(expr.Expression, BinaryOperatorType.InEquality, new PrimitiveExpression(0));
}
} }
} }

2
ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs → ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs

@ -20,7 +20,7 @@ using System;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.Decompiler.Ast namespace ICSharpCode.Decompiler.CSharp
{ {
static class NRefactoryExtensions static class NRefactoryExtensions
{ {

38
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -1,5 +1,6 @@
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -8,16 +9,49 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
{ {
class StatementBuilder class StatementBuilder(ICompilation compilation)
{ {
readonly ExpressionBuilder exprBuilder = new ExpressionBuilder(); readonly ExpressionBuilder exprBuilder = new ExpressionBuilder(compilation);
public Statement Convert(ILInstruction inst) public Statement Convert(ILInstruction inst)
{ {
switch (inst.OpCode) { switch (inst.OpCode) {
case OpCode.BlockContainer:
return ConvertBlockContainer((BlockContainer)inst);
case OpCode.Ret:
if (inst is ReturnVoidInstruction)
return new ReturnStatement().WithAnnotation(inst);
return new ReturnStatement(ConvertUnaryArg(inst)).WithAnnotation(inst);
case OpCode.Throw:
return new ThrowStatement(ConvertUnaryArg(inst)).WithAnnotation(inst);
case OpCode.ConditionalBranch:
return ConvertConditionalBranch((ConditionalBranch)inst);
default: default:
return new ExpressionStatement(exprBuilder.Convert(inst)); return new ExpressionStatement(exprBuilder.Convert(inst));
} }
} }
private Statement ConvertConditionalBranch(ConditionalBranch inst)
{
var condition = exprBuilder.ConvertCondition(inst.Condition);
return new IfElseStatement(condition, new GotoStatement(inst.TargetLabel));
}
private Expression ConvertUnaryArg(ILInstruction inst)
{
return exprBuilder.Convert(((UnaryInstruction)inst).Operand);
}
public BlockStatement ConvertBlockContainer(BlockContainer container)
{
BlockStatement blockStatement = new BlockStatement();
foreach (var block in container.Blocks) {
blockStatement.Add(new LabelStatement { Label = block.Label });
foreach (var inst in block.Instructions) {
blockStatement.Add(Convert(inst));
}
}
return blockStatement;
}
} }
} }

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -65,6 +65,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="CSharp\CSharpDecompiler.cs" /> <Compile Include="CSharp\CSharpDecompiler.cs" />
<Compile Include="CSharp\ExpressionBuilder.cs" /> <Compile Include="CSharp\ExpressionBuilder.cs" />
<Compile Include="CSharp\NRefactoryExtensions.cs" />
<Compile Include="CSharp\StatementBuilder.cs" /> <Compile Include="CSharp\StatementBuilder.cs" />
<Compile Include="TypesHierarchyHelpers.cs" /> <Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" /> <Compile Include="CecilExtensions.cs" />

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

@ -24,9 +24,17 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
/// <summary>
/// Gets the name of this block.
/// </summary>
public string Label
{
get { return Disassembler.DisassemblerHelpers.OffsetToString(this.ILRange.Start); }
}
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
output.WriteDefinition("Block " + Disassembler.DisassemblerHelpers.OffsetToString(this.ILRange.Start), this); output.WriteDefinition("Block " + Label, this);
output.WriteLine(" {"); output.WriteLine(" {");
output.Indent(); output.Indent();
foreach (var inst in Instructions) { foreach (var inst in Instructions) {

6
ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs

@ -11,13 +11,17 @@ namespace ICSharpCode.Decompiler.IL
/// </summary> /// </summary>
class Branch(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode) class Branch(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode)
{ {
public string TargetLabel {
get { return CecilExtensions.OffsetToString(TargetILOffset); }
}
public override bool IsPeeking { get { return false; } } public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
output.Write(OpCode.ToString()); output.Write(OpCode.ToString());
output.Write(' '); output.Write(' ');
output.WriteReference(CecilExtensions.OffsetToString(TargetILOffset), TargetILOffset, isLocal: true); output.WriteReference(TargetLabel, TargetILOffset, isLocal: true);
} }
public override bool IsEndReachable public override bool IsEndReachable

Loading…
Cancel
Save