Browse Source

Add support for decimal literals. Closes #42.

pull/70/head
Daniel Grunwald 15 years ago
parent
commit
27ff71ada3
  1. 1
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 1
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  3. 91
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  4. 3
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

1
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -531,6 +531,7 @@ namespace Decompiler @@ -531,6 +531,7 @@ namespace Decompiler
case Code.Ldc_I8:
case Code.Ldc_R4:
case Code.Ldc_R8:
case (Code)ILCode.Ldc_Decimal:
return new Ast.PrimitiveExpression(operand);
case Code.Ldfld:
if (arg1 is DirectionExpression)

1
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -262,6 +262,7 @@ namespace Decompiler @@ -262,6 +262,7 @@ namespace Decompiler
TernaryOp, // ?:
LoopBreak,
LoopContinue,
Ldc_Decimal,
Pattern // used for ILAst pattern nodes
}

91
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Linq;
using ICSharpCode.NRefactory.Utils;
using Mono.Cecil;
namespace Decompiler
{
@ -16,29 +17,93 @@ namespace Decompiler @@ -16,29 +17,93 @@ namespace Decompiler
{
public static void Run(DecompilerContext context, ILBlock method)
{
// TODO: move this somewhere else
// Eliminate 'dups':
foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
for (int i = 0; i < expr.Arguments.Count; i++) {
if (expr.Arguments[i].Code == ILCode.Dup)
expr.Arguments[i] = expr.Arguments[i].Arguments[0];
}
}
PeepholeTransform[] transforms = {
PeepholeTransform[] blockTransforms = {
ArrayInitializers.Transform(method)
};
Func<ILExpression, ILExpression>[] exprTransforms = {
EliminateDups,
HandleDecimalConstants
};
// Traverse in post order so that nested blocks are transformed first. This is required so that
// patterns on the parent block can assume that all nested blocks are already transformed.
foreach (var block in TreeTraversal.PostOrder<ILNode>(method, c => c != null ? c.GetChildren() : null).OfType<ILBlock>()) {
// go through the instructions in reverse so that
foreach (var node in TreeTraversal.PostOrder<ILNode>(method, c => c != null ? c.GetChildren() : null)) {
ILBlock block = node as ILBlock;
ILExpression expr;
if (block != null) {
// go through the instructions in reverse so that transforms can build up nested structures inside-out
for (int i = block.Body.Count - 1; i >= 0; i--) {
context.CancellationToken.ThrowIfCancellationRequested();
foreach (var t in transforms) {
expr = block.Body[i] as ILExpression;
if (expr != null) {
// apply expr transforms to top-level expr in block
foreach (var t in exprTransforms)
expr = t(expr);
block.Body[i] = expr;
}
// apply block transforms
foreach (var t in blockTransforms) {
t(block, ref i);
}
}
}
expr = node as ILExpression;
if (expr != null) {
// apply expr transforms to all arguments
for (int i = 0; i < expr.Arguments.Count; i++) {
ILExpression arg = expr.Arguments[i];
foreach (var t in exprTransforms)
arg = t(arg);
expr.Arguments[i] = arg;
}
}
}
}
static ILExpression EliminateDups(ILExpression expr)
{
if (expr.Code == ILCode.Dup)
return expr.Arguments.Single();
else
return expr;
}
static ILExpression HandleDecimalConstants(ILExpression expr)
{
if (expr.Code == ILCode.Newobj) {
MethodReference r = (MethodReference)expr.Operand;
if (r.DeclaringType.Name == "Decimal" && r.DeclaringType.Namespace == "System") {
if (expr.Arguments.Count == 1) {
int? val = GetI4Constant(expr.Arguments[0]);
if (val != null) {
expr.Arguments.Clear();
expr.Code = ILCode.Ldc_Decimal;
expr.Operand = new decimal(val.Value);
expr.InferredType = r.DeclaringType;
}
} else if (expr.Arguments.Count == 5) {
int? lo = GetI4Constant(expr.Arguments[0]);
int? mid = GetI4Constant(expr.Arguments[1]);
int? hi = GetI4Constant(expr.Arguments[2]);
int? isNegative = GetI4Constant(expr.Arguments[3]);
int? scale = GetI4Constant(expr.Arguments[4]);
if (lo != null && mid != null && hi != null && isNegative != null && scale != null) {
expr.Arguments.Clear();
expr.Code = ILCode.Ldc_Decimal;
expr.Operand = new decimal(lo.Value, mid.Value, hi.Value, isNegative.Value != 0, (byte)scale);
expr.InferredType = r.DeclaringType;
}
}
}
}
return expr;
}
static int? GetI4Constant(ILExpression expr)
{
if (expr != null && expr.Code == ILCode.Ldc_I4)
return (int)expr.Operand;
else
return null;
}
}
}

3
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -303,6 +303,9 @@ namespace Decompiler @@ -303,6 +303,9 @@ namespace Decompiler
return typeSystem.Single;
case ILCode.Ldc_R8:
return typeSystem.Double;
case ILCode.Ldc_Decimal:
Debug.Assert(expr.InferredType != null && expr.InferredType.FullName == "System.Decimal");
return expr.InferredType;
case ILCode.Ldtoken:
if (expr.Operand is TypeReference)
return new TypeReference("System", "RuntimeTypeHandle", module, module, true);

Loading…
Cancel
Save