diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 5ac2c3195..cb79b976c 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -168,6 +168,13 @@ namespace ICSharpCode.Decompiler.CSharp .WithRR(new ConstantResolveResult(SpecialType.NullType, null)); } + protected internal override TranslatedExpression VisitLdTypeToken(LdTypeToken inst) + { + return new TypeOfExpression(ConvertType(inst.Type)) + .WithILInstruction(inst) + .WithRR(new TypeResolveResult(compilation.FindType(typeof(Type)))); + } + protected internal override TranslatedExpression VisitLogicNot(LogicNot inst) { return LogicNot(TranslateCondition(inst.Argument)).WithILInstruction(inst); diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index c089a6562..8ce77b8c2 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -632,7 +632,14 @@ namespace ICSharpCode.Decompiler.IL case ILOpCode.Stsfld: return new Void(new StsFld(Pop(), ReadAndDecodeFieldReference())); case ILOpCode.Ldtoken: - return new LdToken((MemberReference)ReadAndDecodeMetadataToken()); + var memberReference = ReadAndDecodeMetadataToken() as MemberReference; + if (memberReference is TypeReference) + return new LdTypeToken(typeSystem.Resolve((TypeReference)memberReference)); + if (memberReference is FieldReference) + return new LdMemberToken(typeSystem.Resolve((FieldReference)memberReference)); + if (memberReference is MethodReference) + return new LdMemberToken(typeSystem.Resolve((MethodReference)memberReference)); + throw new NotImplementedException(); case ILOpCode.Ldvirtftn: return new LdVirtFtn(Pop(), ReadAndDecodeMethodReference()); case ILOpCode.Mkrefany: diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs index 23a765234..8be76a7c1 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.cs +++ b/ICSharpCode.Decompiler/IL/Instructions.cs @@ -119,7 +119,9 @@ namespace ICSharpCode.Decompiler.IL /// Load method pointer LdVirtFtn, /// Loads runtime representation of metadata token - LdToken, + LdTypeToken, + /// Loads runtime representation of metadata token + LdMemberToken, /// Allocates space in the stack frame LocAlloc, /// Returns from the current method or lambda. @@ -1074,15 +1076,38 @@ namespace ICSharpCode.Decompiler.IL } /// Loads runtime representation of metadata token - public sealed partial class LdToken : SimpleInstruction + public sealed partial class LdTypeToken : SimpleInstruction + { + public LdTypeToken(IType type) : base(OpCode.LdTypeToken) + { + this.type = type; + } + readonly IType type; + /// Returns the type operand. + 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); + } + public override T AcceptVisitor(ILVisitor visitor) + { + return visitor.VisitLdTypeToken(this); + } + } + + /// Loads runtime representation of metadata token + public sealed partial class LdMemberToken : SimpleInstruction { - public LdToken(Mono.Cecil.MemberReference member) : base(OpCode.LdToken) + public LdMemberToken(IMember member) : base(OpCode.LdMemberToken) { this.member = member; } - readonly Mono.Cecil.MemberReference member; + readonly IMember member; /// Returns the token operand. - public Mono.Cecil.MemberReference Member { get { return member; } } + public IMember Member { get { return member; } } public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output) { @@ -1092,7 +1117,7 @@ namespace ICSharpCode.Decompiler.IL } public override T AcceptVisitor(ILVisitor visitor) { - return visitor.VisitLdToken(this); + return visitor.VisitLdMemberToken(this); } } @@ -2200,7 +2225,11 @@ namespace ICSharpCode.Decompiler.IL { return Default(inst); } - protected internal virtual T VisitLdToken(LdToken inst) + protected internal virtual T VisitLdTypeToken(LdTypeToken inst) + { + return Default(inst); + } + protected internal virtual T VisitLdMemberToken(LdMemberToken inst) { return Default(inst); } @@ -2406,7 +2435,8 @@ namespace ICSharpCode.Decompiler.IL "ldnull", "ldftn", "ldvirtftn", - "ldtoken", + "ldtypetoken", + "ldmembertoken", "localloc", "ret", "shl", diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt index f3e7b059f..e4c2dfdb8 100644 --- a/ICSharpCode.Decompiler/IL/Instructions.tt +++ b/ICSharpCode.Decompiler/IL/Instructions.tt @@ -122,8 +122,10 @@ CustomClassName("LdFtn"), NoArguments, HasMethodOperand, ResultType("I")), new OpCode("ldvirtftn", "Load method pointer", CustomClassName("LdVirtFtn"), Unary, HasMethodOperand, MayThrow, ResultType("I")), - new OpCode("ldtoken", "Loads runtime representation of metadata token", - CustomClassName("LdToken"), NoArguments, HasTokenOperand, ResultType("O")), + new OpCode("ldtypetoken", "Loads runtime representation of metadata token", + CustomClassName("LdTypeToken"), NoArguments, HasTypeOperand, ResultType("O")), + new OpCode("ldmembertoken", "Loads runtime representation of metadata token", + CustomClassName("LdMemberToken"), NoArguments, HasMemberOperand, ResultType("O")), new OpCode("localloc", "Allocates space in the stack frame", CustomClassName("LocAlloc"), Unary, ResultType("I"), MayThrow), new OpCode("ret", "Returns from the current method or lambda.", @@ -684,12 +686,12 @@ namespace ICSharpCode.Decompiler.IL opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, method);"); }; - static Action HasTokenOperand = opCode => { - opCode.ConstructorParameters.Add("Mono.Cecil.MemberReference member"); - opCode.Members.Add("readonly Mono.Cecil.MemberReference member;"); + static Action HasMemberOperand = opCode => { + opCode.ConstructorParameters.Add("IMember member"); + opCode.Members.Add("readonly IMember member;"); opCode.ConstructorBody.Add("this.member = member;"); opCode.Members.Add("/// Returns the token operand." + Environment.NewLine - + "public Mono.Cecil.MemberReference Member { get { return member; } }"); + + "public IMember Member { get { return member; } }"); opCode.GenerateWriteTo = true; opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, member);");