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

21
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -12,7 +12,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -12,7 +12,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary>
/// Translates from ILAst to C# expressions.
/// </summary>
class ExpressionBuilder
class ExpressionBuilder(private readonly ICompilation compilation)
{
struct ConvertedExpression(public readonly Expression Expression, public readonly IType Type) { }
@ -33,6 +33,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -33,6 +33,14 @@ namespace ICSharpCode.Decompiler.CSharp
ConvertedExpression TransformExpression(ILInstruction inst)
{
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:
return ErrorExpression("OpCode not supported: " + inst.OpCode);
}
@ -44,5 +52,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -44,5 +52,16 @@ namespace ICSharpCode.Decompiler.CSharp
e.AddChild(new Comment(message, CommentType.MultiLine), Roles.Comment);
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; @@ -20,7 +20,7 @@ using System;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.Decompiler.Ast
namespace ICSharpCode.Decompiler.CSharp
{
static class NRefactoryExtensions
{

38
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using ICSharpCode.Decompiler.IL;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using System;
using System.Collections.Generic;
using System.Linq;
@ -8,16 +9,49 @@ using System.Threading.Tasks; @@ -8,16 +9,49 @@ using System.Threading.Tasks;
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)
{
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:
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 @@ @@ -65,6 +65,7 @@
<ItemGroup>
<Compile Include="CSharp\CSharpDecompiler.cs" />
<Compile Include="CSharp\ExpressionBuilder.cs" />
<Compile Include="CSharp\NRefactoryExtensions.cs" />
<Compile Include="CSharp\StatementBuilder.cs" />
<Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />

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

@ -24,9 +24,17 @@ namespace ICSharpCode.Decompiler.IL @@ -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)
{
output.WriteDefinition("Block " + Disassembler.DisassemblerHelpers.OffsetToString(this.ILRange.Start), this);
output.WriteDefinition("Block " + Label, this);
output.WriteLine(" {");
output.Indent();
foreach (var inst in Instructions) {

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

@ -11,13 +11,17 @@ namespace ICSharpCode.Decompiler.IL @@ -11,13 +11,17 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
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 void WriteTo(ITextOutput output)
{
output.Write(OpCode.ToString());
output.Write(' ');
output.WriteReference(CecilExtensions.OffsetToString(TargetILOffset), TargetILOffset, isLocal: true);
output.WriteReference(TargetLabel, TargetILOffset, isLocal: true);
}
public override bool IsEndReachable

Loading…
Cancel
Save