Browse Source

Add support for conv and ldobj opcodes

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
79475a79c5
  1. 60
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 32
      ICSharpCode.Decompiler/IL/NRTypeExtensions.cs

60
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Diagnostics;
using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
@ -89,16 +90,12 @@ namespace ICSharpCode.Decompiler.CSharp
public Expression Convert(ILInstruction inst) public Expression Convert(ILInstruction inst)
{ {
var expr = inst.AcceptVisitor(this).Expression; return ConvertArgument(inst).Expression;
expr.AddAnnotation(inst);
return expr;
} }
public Expression Convert(ILInstruction inst, IType expectedType) public Expression Convert(ILInstruction inst, IType expectedType)
{ {
var expr = inst.AcceptVisitor(this); return ConvertArgument(inst).ConvertTo(expectedType, this);
expr.Expression.AddAnnotation(inst);
return expr.ConvertTo(expectedType, this);
} }
public AstType ConvertType(Mono.Cecil.TypeReference type) public AstType ConvertType(Mono.Cecil.TypeReference type)
@ -118,6 +115,7 @@ namespace ICSharpCode.Decompiler.CSharp
ConvertedExpression ConvertArgument(ILInstruction inst) ConvertedExpression ConvertArgument(ILInstruction inst)
{ {
var cexpr = inst.AcceptVisitor(this); var cexpr = inst.AcceptVisitor(this);
Debug.Assert(cexpr.Type.GetStackType() == inst.ResultType || cexpr.Type.Kind == TypeKind.Unknown || inst.ResultType == StackType.Void);
cexpr.Expression.AddAnnotation(inst); cexpr.Expression.AddAnnotation(inst);
return cexpr; return cexpr;
} }
@ -272,11 +270,36 @@ namespace ICSharpCode.Decompiler.CSharp
return HandleBinaryNumeric(inst, BinaryOperatorType.Subtract); return HandleBinaryNumeric(inst, BinaryOperatorType.Subtract);
} }
protected internal override ConvertedExpression VisitMul(Mul inst)
{
return HandleBinaryNumeric(inst, BinaryOperatorType.Multiply);
}
protected internal override ConvertedExpression VisitDiv(Div inst)
{
return HandleBinaryNumeric(inst, BinaryOperatorType.Divide);
}
protected internal override ConvertedExpression VisitRem(Rem inst)
{
return HandleBinaryNumeric(inst, BinaryOperatorType.Modulus);
}
protected internal override ConvertedExpression VisitBitXor(BitXor inst) protected internal override ConvertedExpression VisitBitXor(BitXor inst)
{ {
return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr); return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr);
} }
protected internal override ConvertedExpression VisitBitAnd(BitAnd inst)
{
return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseAnd);
}
protected internal override ConvertedExpression VisitBitOr(BitOr inst)
{
return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseOr);
}
protected internal override ConvertedExpression VisitShl(Shl inst) protected internal override ConvertedExpression VisitShl(Shl inst)
{ {
return HandleBinaryNumeric(inst, BinaryOperatorType.ShiftLeft); return HandleBinaryNumeric(inst, BinaryOperatorType.ShiftLeft);
@ -314,6 +337,21 @@ namespace ICSharpCode.Decompiler.CSharp
return sign == Sign.None || type.GetSign() == sign; return sign == Sign.None || type.GetSign() == sign;
} }
protected internal override ConvertedExpression VisitConv(Conv inst)
{
var arg = ConvertArgument(inst.Argument);
Expression input = arg.Expression;
if (arg.Type.GetSign() != inst.Sign) {
// we need to cast the input to a type of appropriate sign
var inputType = inst.Argument.ResultType.ToKnownTypeCode(inst.Sign);
input = arg.ConvertTo(compilation.FindType(inputType), this);
}
var targetType = compilation.FindType(inst.TargetType.ToKnownTypeCode());
return new ConvertedExpression(
new CastExpression(astBuilder.ConvertType(targetType), input),
targetType);
}
protected internal override ConvertedExpression VisitCall(Call inst) protected internal override ConvertedExpression VisitCall(Call inst)
{ {
return HandleCallInstruction(inst); return HandleCallInstruction(inst);
@ -346,6 +384,16 @@ namespace ICSharpCode.Decompiler.CSharp
} }
return new ConvertedExpression(invocation, cecilMapper.GetType(inst.Method.ReturnType)); return new ConvertedExpression(invocation, cecilMapper.GetType(inst.Method.ReturnType));
} }
protected internal override ConvertedExpression VisitLdObj(LdObj inst)
{
var target = ConvertArgument(inst.Target);
var pointerType = new PointerType(cecilMapper.GetType(inst.Type));
return new ConvertedExpression(
new UnaryOperatorExpression(
UnaryOperatorType.Dereference, target.ConvertTo(pointerType, this)),
pointerType.ElementType);
}
protected override ConvertedExpression Default(ILInstruction inst) protected override ConvertedExpression Default(ILInstruction inst)
{ {

32
ICSharpCode.Decompiler/IL/NRTypeExtensions.cs

@ -95,6 +95,38 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
public static KnownTypeCode ToKnownTypeCode(this PrimitiveType primitiveType)
{
switch (primitiveType) {
case PrimitiveType.I1:
return KnownTypeCode.SByte;
case PrimitiveType.I2:
return KnownTypeCode.Int16;
case PrimitiveType.I4:
return KnownTypeCode.Int32;
case PrimitiveType.I8:
return KnownTypeCode.Int64;
case PrimitiveType.R4:
return KnownTypeCode.Single;
case PrimitiveType.R8:
return KnownTypeCode.Double;
case PrimitiveType.U1:
return KnownTypeCode.Byte;
case PrimitiveType.U2:
return KnownTypeCode.UInt16;
case PrimitiveType.U4:
return KnownTypeCode.UInt32;
case PrimitiveType.U8:
return KnownTypeCode.UInt64;
case PrimitiveType.I:
return KnownTypeCode.IntPtr;
case PrimitiveType.U:
return KnownTypeCode.UIntPtr;
default:
return KnownTypeCode.None;
}
}
public static KnownTypeCode ToKnownTypeCode(this StackType stackType, Sign sign = Sign.None) public static KnownTypeCode ToKnownTypeCode(this StackType stackType, Sign sign = Sign.None)
{ {
switch (stackType) { switch (stackType) {

Loading…
Cancel
Save