Browse Source

add support for mkreftype, refanytype, refanyvalue, arglist

pull/728/head
Siegfried Pammer 10 years ago
parent
commit
0515750574
  1. 43
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 53
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 148
      ICSharpCode.Decompiler/IL/Instructions.cs
  4. 9
      ICSharpCode.Decompiler/IL/Instructions.tt

43
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -28,8 +28,6 @@ using ICSharpCode.NRefactory.TypeSystem; @@ -28,8 +28,6 @@ using ICSharpCode.NRefactory.TypeSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.CSharp
{
@ -734,6 +732,47 @@ namespace ICSharpCode.Decompiler.CSharp @@ -734,6 +732,47 @@ namespace ICSharpCode.Decompiler.CSharp
{
return Translate(inst.Argument).ConvertTo(inst.Type, this);
}
protected internal override TranslatedExpression VisitArglist(Arglist inst)
{
return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }
.WithILInstruction(inst)
.WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "RuntimeArgumentHandle"))));
}
protected internal override TranslatedExpression VisitMakeRefAny(MakeRefAny inst)
{
var arg = Translate(inst.Argument).Expression;
if (arg is DirectionExpression) {
arg = ((DirectionExpression)arg).Expression;
}
return new UndocumentedExpression {
UndocumentedExpressionType = UndocumentedExpressionType.MakeRef,
Arguments = { arg.Detach() }
}
.WithILInstruction(inst)
.WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "TypedReference"))));
}
protected internal override TranslatedExpression VisitRefAnyType(RefAnyType inst)
{
return new UndocumentedExpression {
UndocumentedExpressionType = UndocumentedExpressionType.RefType,
Arguments = { Translate(inst.Argument).Expression.Detach() }
}.Member("TypeHandle")
.WithILInstruction(inst)
.WithRR(new TypeResolveResult(compilation.FindType(new TopLevelTypeName("System", "RuntimeTypeHandle"))));
}
protected internal override TranslatedExpression VisitRefAnyValue(RefAnyValue inst)
{
var expr = new UndocumentedExpression {
UndocumentedExpressionType = UndocumentedExpressionType.RefValue,
Arguments = { Translate(inst.Argument).Expression, new TypeReferenceExpression(ConvertType(inst.Type)) }
};
return new DirectionExpression(FieldDirection.Ref, expr.WithILInstruction(inst)).WithoutILInstruction()
.WithRR(new ByReferenceResolveResult(inst.Type, false));
}
protected override TranslatedExpression Default(ILInstruction inst)
{

53
ICSharpCode.Decompiler/IL/ILReader.cs

@ -691,13 +691,13 @@ namespace ICSharpCode.Decompiler.IL @@ -691,13 +691,13 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldvirtftn:
return Push(new LdVirtFtn(Pop(), ReadAndDecodeMethodReference()));
case ILOpCode.Mkrefany:
throw new NotImplementedException();
return Push(new MakeRefAny(Pop(), ReadAndDecodeTypeReference()));
case ILOpCode.Newarr:
return Push(new NewArr(ReadAndDecodeTypeReference(), Pop()));
case ILOpCode.Refanytype:
throw new NotImplementedException();
return Push(new RefAnyType(Pop()));
case ILOpCode.Refanyval:
throw new NotImplementedException();
return Push(new RefAnyValue(Pop(), ReadAndDecodeTypeReference()));
case ILOpCode.Rethrow:
return new Rethrow();
case ILOpCode.Sizeof:
@ -806,6 +806,8 @@ namespace ICSharpCode.Decompiler.IL @@ -806,6 +806,8 @@ namespace ICSharpCode.Decompiler.IL
LdLoc Pop()
{
if (currentStack.IsEmpty)
Debugger.Break();
// TODO: handle stack underflow?
ILVariable v;
currentStack = currentStack.Pop(out v);
@ -938,31 +940,30 @@ namespace ICSharpCode.Decompiler.IL @@ -938,31 +940,30 @@ namespace ICSharpCode.Decompiler.IL
for (int i = arguments.Length - 1; i >= 0; i--) {
arguments[i] = Pop();
}
ILInstruction result;
if (method.DeclaringType.Kind == TypeKind.Array) {
var type = ((ICSharpCode.NRefactory.TypeSystem.ArrayType)method.DeclaringType).ElementType;
if (opCode == OpCode.NewObj) {
result = new NewArr(type, arguments);
} else if (method.Name == "Set") {
var target = arguments[0].Clone();
var value = arguments.Last().Clone();
var indices = arguments.Skip(1).Take(arguments.Length - 2).ToArray();
result = new StObj(new LdElema(type, target, indices), value, type);
} else if (method.Name == "Get") {
var target = arguments[0].Clone();
var indices = arguments.Skip(1).ToArray();
result = new LdObj(new LdElema(type, target, indices), type);
} else
switch (method.DeclaringType.Kind) {
case TypeKind.Array:
var type = ((ICSharpCode.NRefactory.TypeSystem.ArrayType)method.DeclaringType).ElementType;
if (opCode == OpCode.NewObj)
return Push(new NewArr(type, arguments));
if (method.Name == "Set") {
var target = arguments[0];
var value = arguments.Last();
var indices = arguments.Skip(1).Take(arguments.Length - 2).ToArray();
return new StObj(new LdElema(type, target, indices), value, type);
}
if (method.Name == "Get") {
var target = arguments[0];
var indices = arguments.Skip(1).ToArray();
return Push(new LdObj(new LdElema(type, target, indices), type));
}
throw new NotImplementedException();
} else {
var call = CallInstruction.Create(opCode, method);
call.Arguments.AddRange(arguments);
result = call;
default:
var call = CallInstruction.Create(opCode, method);
call.Arguments.AddRange(arguments);
if (call.ResultType != StackType.Void)
return Push(call);
return call;
}
if (result.ResultType != StackType.Void)
return Push(result);
else
return result;
}
static int GetPopCount(OpCode callCode, MethodReference methodReference)

148
ICSharpCode.Decompiler/IL/Instructions.cs

@ -173,6 +173,12 @@ namespace ICSharpCode.Decompiler.IL @@ -173,6 +173,12 @@ namespace ICSharpCode.Decompiler.IL
LdLen,
/// <summary>Load address of array element.</summary>
LdElema,
/// <summary>Push a typed reference of type class onto the stack.</summary>
MakeRefAny,
/// <summary>Push the type token stored in a typed reference.</summary>
RefAnyType,
/// <summary>Push the address stored in a typed reference.</summary>
RefAnyValue,
}
/// <summary>Instruction without any arguments</summary>
@ -2899,6 +2905,87 @@ namespace ICSharpCode.Decompiler.IL @@ -2899,6 +2905,87 @@ namespace ICSharpCode.Decompiler.IL
}
}
/// <summary>Push a typed reference of type class onto the stack.</summary>
public sealed partial class MakeRefAny : UnaryInstruction
{
public MakeRefAny(ILInstruction argument, IType type) : base(OpCode.MakeRefAny, argument)
{
this.type = type;
}
readonly IType type;
/// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, type);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitMakeRefAny(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitMakeRefAny(this);
}
}
/// <summary>Push the type token stored in a typed reference.</summary>
public sealed partial class RefAnyType : UnaryInstruction
{
public RefAnyType(ILInstruction argument) : base(OpCode.RefAnyType, argument)
{
}
public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitRefAnyType(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitRefAnyType(this);
}
}
/// <summary>Push the address stored in a typed reference.</summary>
public sealed partial class RefAnyValue : UnaryInstruction
{
public RefAnyValue(ILInstruction argument, IType type) : base(OpCode.RefAnyValue, argument)
{
this.type = type;
}
readonly IType type;
/// <summary>Returns the type operand.</summary>
public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, type);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitRefAnyValue(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitRefAnyValue(this);
}
}
/// <summary>
/// Base class for visitor pattern.
@ -3196,6 +3283,18 @@ namespace ICSharpCode.Decompiler.IL @@ -3196,6 +3283,18 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
protected internal virtual void VisitMakeRefAny(MakeRefAny inst)
{
Default(inst);
}
protected internal virtual void VisitRefAnyType(RefAnyType inst)
{
Default(inst);
}
protected internal virtual void VisitRefAnyValue(RefAnyValue inst)
{
Default(inst);
}
}
/// <summary>
@ -3494,6 +3593,18 @@ namespace ICSharpCode.Decompiler.IL @@ -3494,6 +3593,18 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
protected internal virtual T VisitMakeRefAny(MakeRefAny inst)
{
return Default(inst);
}
protected internal virtual T VisitRefAnyType(RefAnyType inst)
{
return Default(inst);
}
protected internal virtual T VisitRefAnyValue(RefAnyValue inst)
{
return Default(inst);
}
}
partial class BinaryNumericInstruction
@ -3623,6 +3734,9 @@ namespace ICSharpCode.Decompiler.IL @@ -3623,6 +3734,9 @@ namespace ICSharpCode.Decompiler.IL
"sizeof",
"ldlen",
"ldelema",
"mkrefany",
"refanytype",
"refanyval",
};
}
@ -4244,6 +4358,40 @@ namespace ICSharpCode.Decompiler.IL @@ -4244,6 +4358,40 @@ namespace ICSharpCode.Decompiler.IL
array = default(ILInstruction);
return false;
}
public bool MatchMakeRefAny(out ILInstruction argument, out IType type)
{
var inst = this as MakeRefAny;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
public bool MatchRefAnyType(out ILInstruction argument)
{
var inst = this as RefAnyType;
if (inst != null) {
argument = inst.Argument;
return true;
}
argument = default(ILInstruction);
return false;
}
public bool MatchRefAnyValue(out ILInstruction argument, out IType type)
{
var inst = this as RefAnyValue;
if (inst != null) {
argument = inst.Argument;
type = inst.Type;
return true;
}
argument = default(ILInstruction);
type = default(IType);
return false;
}
}
}

9
ICSharpCode.Decompiler/IL/Instructions.tt

@ -192,7 +192,14 @@ @@ -192,7 +192,14 @@
CustomClassName("LdLen"), CustomArguments("array"), MayThrow, ResultType("I")),
new OpCode("ldelema", "Load address of array element.",
CustomClassName("LdElema"), HasTypeOperand, CustomChildren(new [] { new ArgumentInfo("array"), new ArgumentInfo("indices") { IsCollection = true } }, true),
MayThrow, ResultType("Ref"), SupportsReadonlyPrefix)
MayThrow, ResultType("Ref"), SupportsReadonlyPrefix),
new OpCode("mkrefany", "Push a typed reference of type class onto the stack.",
CustomClassName("MakeRefAny"), Unary, HasTypeOperand, ResultType("O")),
new OpCode("refanytype", "Push the type token stored in a typed reference.",
CustomClassName("RefAnyType"), Unary, ResultType("O")),
new OpCode("refanyval", "Push the address stored in a typed reference.",
CustomClassName("RefAnyValue"), Unary, HasTypeOperand, MayThrow, ResultType("Ref")),
};
#>
using System;

Loading…
Cancel
Save