Browse Source

Use NRefactory.TypeSystem for ILAst.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
2f83334c2e
  1. 87
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 91
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 116
      ICSharpCode.Decompiler/CSharp/NRefactoryCecilMapper.cs
  4. 4
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  5. 4
      ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs
  6. 38
      ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs
  7. 14
      ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs
  8. 30
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
  9. 21
      ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs
  10. 296
      ICSharpCode.Decompiler/DecompilerTypeSystem.cs
  11. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  12. 8
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  13. 179
      ICSharpCode.Decompiler/IL/ILReader.cs
  14. 5
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  15. 36
      ICSharpCode.Decompiler/IL/ILVariable.cs
  16. 12
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  17. 136
      ICSharpCode.Decompiler/IL/Instructions.cs
  18. 36
      ICSharpCode.Decompiler/IL/Instructions.tt
  19. 21
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  20. 8
      ICSharpCode.Decompiler/ReferenceResolvingException.cs
  21. 3
      ICSharpCode.Decompiler/Tests/Helpers/Tester.cs
  22. 3
      ILSpy.BamlDecompiler/Tests/TestRunner.cs
  23. 6
      ILSpy/Languages/ILAstLanguage.cs

87
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -35,27 +35,9 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
public class CSharpDecompiler public class CSharpDecompiler
{ {
CecilLoader cecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true }; readonly DecompilerTypeSystem typeSystem;
Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>();
NRefactoryCecilMapper cecilMapper;
ICompilation compilation;
TypeSystemAstBuilder typeSystemAstBuilder; TypeSystemAstBuilder typeSystemAstBuilder;
List<IAstTransform> astTransforms = new List<IAstTransform> { List<IAstTransform> astTransforms;
//new PushNegation(),
//new DelegateConstruction(context),
//new PatternStatementTransform(context),
new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(),
new AddCheckedBlocks(),
//new DeclareVariables(context), // should run after most transforms that modify statements
new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
//new DecimalConstantTransform(),
//new IntroduceUsingDeclarations(context),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(),
};
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
@ -67,50 +49,49 @@ namespace ICSharpCode.Decompiler.CSharp
} }
public CSharpDecompiler(ModuleDefinition module) public CSharpDecompiler(ModuleDefinition module)
: this(new DecompilerTypeSystem(module))
{ {
cecilLoader.OnEntityLoaded = (entity, mr) => { }
// entityDict needs locking because the type system is multi-threaded and may be accessed externally
lock (entityDict)
entityDict[entity] = mr;
};
IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(module); public CSharpDecompiler(DecompilerTypeSystem typeSystem)
var referencedAssemblies = new List<IUnresolvedAssembly>(); {
foreach (var asmRef in module.AssemblyReferences) { if (typeSystem == null)
var asm = module.AssemblyResolver.Resolve(asmRef); throw new ArgumentNullException("typeSystem");
if (asm != null) this.typeSystem = typeSystem;
referencedAssemblies.Add(cecilLoader.LoadAssembly(asm));
} astTransforms = new List<IAstTransform> {
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); //new PushNegation(),
cecilMapper = new NRefactoryCecilMapper(compilation, module, GetMemberReference); //new DelegateConstruction(context),
//new PatternStatementTransform(context),
new ReplaceMethodCallsWithOperators(),
new IntroduceUnsafeModifier(),
new AddCheckedBlocks(),
//new DeclareVariables(context), // should run after most transforms that modify statements
new ConvertConstructorCallIntoInitializer(typeSystem), // must run after DeclareVariables
//new DecimalConstantTransform(),
//new IntroduceUsingDeclarations(context),
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
//new CombineQueryExpressions(context),
//new FlattenSwitchBlocks(),
};
typeSystemAstBuilder = new TypeSystemAstBuilder(); typeSystemAstBuilder = new TypeSystemAstBuilder();
typeSystemAstBuilder.AlwaysUseShortTypeNames = true; typeSystemAstBuilder.AlwaysUseShortTypeNames = true;
typeSystemAstBuilder.AddAnnotations = true; typeSystemAstBuilder.AddAnnotations = true;
} }
MemberReference GetMemberReference(IUnresolvedEntity member)
{
lock (entityDict) {
MemberReference mr;
if (member != null && entityDict.TryGetValue(member, out mr))
return mr;
}
return null;
}
void RunTransforms(AstNode rootNode) void RunTransforms(AstNode rootNode)
{ {
var context = new TransformContext(compilation, cecilMapper);
foreach (var transform in astTransforms) foreach (var transform in astTransforms)
transform.Run(rootNode, context); transform.Run(rootNode);
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
} }
public SyntaxTree DecompileWholeModuleAsSingleFile() public SyntaxTree DecompileWholeModuleAsSingleFile()
{ {
SyntaxTree syntaxTree = new SyntaxTree(); SyntaxTree syntaxTree = new SyntaxTree();
foreach (var g in compilation.MainAssembly.TopLevelTypeDefinitions.GroupBy(t => t.Namespace)) { foreach (var g in typeSystem.Compilation.MainAssembly.TopLevelTypeDefinitions.GroupBy(t => t.Namespace)) {
AstNode groupNode; AstNode groupNode;
if (string.IsNullOrEmpty(g.Key)) { if (string.IsNullOrEmpty(g.Key)) {
groupNode = syntaxTree; groupNode = syntaxTree;
@ -135,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
if (typeDefinition == null) if (typeDefinition == null)
throw new ArgumentNullException("typeDefinition"); throw new ArgumentNullException("typeDefinition");
ITypeDefinition typeDef = cecilMapper.GetType(typeDefinition).GetDefinition(); ITypeDefinition typeDef = typeSystem.GetType(typeDefinition).GetDefinition();
if (typeDef == null) if (typeDef == null)
throw new InvalidOperationException("Could not find type definition in NR type system"); throw new InvalidOperationException("Could not find type definition in NR type system");
var decl = DoDecompile(typeDef); var decl = DoDecompile(typeDef);
@ -152,7 +133,7 @@ namespace ICSharpCode.Decompiler.CSharp
return entityDecl; return entityDecl;
} }
foreach (var method in typeDef.Methods) { foreach (var method in typeDef.Methods) {
var methodDef = cecilMapper.GetCecil(method) as MethodDefinition; var methodDef = typeSystem.GetCecil(method) as MethodDefinition;
if (methodDef != null) { if (methodDef != null) {
var memberDecl = DoDecompile(methodDef, method); var memberDecl = DoDecompile(methodDef, method);
typeDecl.Members.Add(memberDecl); typeDecl.Members.Add(memberDecl);
@ -165,7 +146,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
if (methodDefinition == null) if (methodDefinition == null)
throw new ArgumentNullException("methodDefinition"); throw new ArgumentNullException("methodDefinition");
var method = cecilMapper.GetMethod(methodDefinition); var method = typeSystem.GetMethod(methodDefinition);
if (method == null) if (method == null)
throw new InvalidOperationException("Could not find method in NR type system"); throw new InvalidOperationException("Could not find method in NR type system");
var decl = DoDecompile(methodDefinition, method); var decl = DoDecompile(methodDefinition, method);
@ -177,19 +158,19 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
var entityDecl = typeSystemAstBuilder.ConvertEntity(method); var entityDecl = typeSystemAstBuilder.ConvertEntity(method);
if (methodDefinition.HasBody) { if (methodDefinition.HasBody) {
var ilReader = new ILReader(); var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken); var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken);
function.CheckInvariant(); function.CheckInvariant();
function.Body = function.Body.AcceptVisitor(new TransformingVisitor()); function.Body = function.Body.AcceptVisitor(new TransformingVisitor());
function.CheckInvariant(); function.CheckInvariant();
var statementBuilder = new StatementBuilder(method, cecilMapper); var statementBuilder = new StatementBuilder(method);
var body = statementBuilder.ConvertAsBlock(function.Body); var body = statementBuilder.ConvertAsBlock(function.Body);
// insert variables at start of body // insert variables at start of body
Statement prevVarDecl = null; Statement prevVarDecl = null;
foreach (var v in function.Variables) { foreach (var v in function.Variables) {
if (v.Kind == VariableKind.Local) { if (v.Kind == VariableKind.Local) {
var type = typeSystemAstBuilder.ConvertType(cecilMapper.GetType(v.Type)); var type = typeSystemAstBuilder.ConvertType(v.Type);
var varDecl = new VariableDeclarationStatement(type, v.Name); var varDecl = new VariableDeclarationStatement(type, v.Name);
body.Statements.InsertAfter(prevVarDecl, varDecl); body.Statements.InsertAfter(prevVarDecl, varDecl);
prevVarDecl = varDecl; prevVarDecl = varDecl;

91
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -38,28 +38,17 @@ namespace ICSharpCode.Decompiler.CSharp
class ExpressionBuilder : ILVisitor<TranslatedExpression> class ExpressionBuilder : ILVisitor<TranslatedExpression>
{ {
internal readonly ICompilation compilation; internal readonly ICompilation compilation;
internal readonly NRefactoryCecilMapper cecilMapper;
internal readonly CSharpResolver resolver; internal readonly CSharpResolver resolver;
internal readonly TypeSystemAstBuilder astBuilder; internal readonly TypeSystemAstBuilder astBuilder;
public ExpressionBuilder(ICompilation compilation, NRefactoryCecilMapper cecilMapper) public ExpressionBuilder(ICompilation compilation)
{ {
Debug.Assert(compilation != null); Debug.Assert(compilation != null);
Debug.Assert(cecilMapper != null);
this.compilation = compilation; this.compilation = compilation;
this.cecilMapper = cecilMapper;
this.resolver = new CSharpResolver(compilation); this.resolver = new CSharpResolver(compilation);
this.astBuilder = new TypeSystemAstBuilder(resolver); this.astBuilder = new TypeSystemAstBuilder(resolver);
} }
public AstType ConvertType(Mono.Cecil.TypeReference typeReference)
{
if (typeReference == null)
return AstType.Null;
var type = cecilMapper.GetType(typeReference);
return ConvertType(type);
}
public AstType ConvertType(IType type) public AstType ConvertType(IType type)
{ {
var astType = astBuilder.ConvertType(type); var astType = astBuilder.ConvertType(type);
@ -89,36 +78,34 @@ namespace ICSharpCode.Decompiler.CSharp
else else
expr = new IdentifierExpression(variable.Name); expr = new IdentifierExpression(variable.Name);
// TODO: use LocalResolveResult instead // TODO: use LocalResolveResult instead
if (variable.Type.SkipModifiers().MetadataType == Mono.Cecil.MetadataType.ByReference) { if (variable.Type.Kind == TypeKind.ByReference) {
// When loading a by-ref parameter, use 'ref paramName'. // When loading a by-ref parameter, use 'ref paramName'.
// We'll strip away the 'ref' when dereferencing. // We'll strip away the 'ref' when dereferencing.
// Ensure that the IdentifierExpression itself also gets a resolve result, as that might // Ensure that the IdentifierExpression itself also gets a resolve result, as that might
// get used after the 'ref' is stripped away: // get used after the 'ref' is stripped away:
var elementType = variable.Type.SkipModifiers().GetElementType(); var elementType = ((ByReferenceType)variable.Type).ElementType;
expr.WithRR(new ResolveResult(cecilMapper.GetType(elementType))); expr.WithRR(new ResolveResult(elementType));
expr = new DirectionExpression(FieldDirection.Ref, expr); expr = new DirectionExpression(FieldDirection.Ref, expr);
} }
return expr.WithRR(new ResolveResult(cecilMapper.GetType(variable.Type))); return expr.WithRR(new ResolveResult(variable.Type));
} }
TranslatedExpression IsType(IsInst inst) TranslatedExpression IsType(IsInst inst)
{ {
var arg = Translate(inst.Argument); var arg = Translate(inst.Argument);
var type = cecilMapper.GetType(inst.Type); return new IsExpression(arg.Expression, ConvertType(inst.Type))
return new IsExpression(arg.Expression, ConvertType(type))
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new TypeIsResolveResult(arg.ResolveResult, type, compilation.FindType(TypeCode.Boolean))); .WithRR(new TypeIsResolveResult(arg.ResolveResult, inst.Type, compilation.FindType(TypeCode.Boolean)));
} }
protected internal override TranslatedExpression VisitIsInst(IsInst inst) protected internal override TranslatedExpression VisitIsInst(IsInst inst)
{ {
var arg = Translate(inst.Argument); var arg = Translate(inst.Argument);
var type = cecilMapper.GetType(inst.Type); return new AsExpression(arg.Expression, ConvertType(inst.Type))
return new AsExpression(arg.Expression, ConvertType(type))
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ConversionResolveResult(type, arg.ResolveResult, Conversion.TryCast)); .WithRR(new ConversionResolveResult(inst.Type, arg.ResolveResult, Conversion.TryCast));
} }
protected internal override TranslatedExpression VisitNewObj(NewObj inst) protected internal override TranslatedExpression VisitNewObj(NewObj inst)
@ -374,52 +361,36 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression HandleCallInstruction(CallInstruction inst) TranslatedExpression HandleCallInstruction(CallInstruction inst)
{ {
// Used for Call, CallVirt and NewObj // Used for Call, CallVirt and NewObj
var method = cecilMapper.GetMethod(inst.Method);
TranslatedExpression target; TranslatedExpression target;
if (inst.OpCode == OpCode.NewObj) { if (inst.OpCode == OpCode.NewObj) {
target = default(TranslatedExpression); // no target target = default(TranslatedExpression); // no target
} else if (inst.Method.HasThis) { } else if (!inst.Method.IsStatic) {
var argInstruction = inst.Arguments[0]; var argInstruction = inst.Arguments[0];
if (inst.OpCode == OpCode.Call && argInstruction.MatchLdThis()) { if (inst.OpCode == OpCode.Call && argInstruction.MatchLdThis()) {
target = new BaseReferenceExpression() target = new BaseReferenceExpression()
.WithILInstruction(argInstruction) .WithILInstruction(argInstruction)
.WithRR(new ThisResolveResult(cecilMapper.GetType(inst.Method.DeclaringType), causesNonVirtualInvocation: true)); .WithRR(new ThisResolveResult(inst.Method.DeclaringType, causesNonVirtualInvocation: true));
} else { } else {
target = Translate(argInstruction); target = Translate(argInstruction);
} }
} else { } else {
var declaringType = cecilMapper.GetType(inst.Method.DeclaringType); target = new TypeReferenceExpression(ConvertType(inst.Method.DeclaringType))
target = new TypeReferenceExpression(ConvertType(declaringType))
.WithoutILInstruction() .WithoutILInstruction()
.WithRR(new TypeResolveResult(declaringType)); .WithRR(new TypeResolveResult(inst.Method.DeclaringType));
} }
var arguments = inst.Arguments.SelectArray(Translate); var arguments = inst.Arguments.SelectArray(Translate);
int firstParamIndex = (inst.Method.HasThis && inst.OpCode != OpCode.NewObj) ? 1 : 0; int firstParamIndex = (inst.Method.IsStatic || inst.OpCode == OpCode.NewObj) ? 0 : 1;
// Translate arguments to the expected parameter types
Debug.Assert(arguments.Length == firstParamIndex + inst.Method.Parameters.Count); Debug.Assert(arguments.Length == firstParamIndex + inst.Method.Parameters.Count);
ResolveResult rr; for (int i = firstParamIndex; i < arguments.Length; i++) {
if (method != null) { var parameter = inst.Method.Parameters[i - firstParamIndex];
// Translate arguments to the expected parameter types arguments[i] = arguments[i].ConvertTo(parameter.Type, this);
Debug.Assert(arguments.Length == firstParamIndex + method.Parameters.Count);
for (int i = firstParamIndex; i < arguments.Length; i++) {
var parameter = method.Parameters[i - firstParamIndex];
arguments[i] = arguments[i].ConvertTo(parameter.Type, this);
}
var argumentResolveResults = arguments.Skip(firstParamIndex).Select(arg => arg.ResolveResult).ToList();
rr = new CSharpInvocationResolveResult(target.ResolveResult, method, argumentResolveResults);
} else {
// no IMethod found -- determine the target types from the cecil parameter collection instead
for (int i = firstParamIndex; i < arguments.Length; i++) {
var parameterDefinition = inst.Method.Parameters[i - firstParamIndex];
var parameterType = cecilMapper.GetType(parameterDefinition.ParameterType);
arguments[i] = arguments[i].ConvertTo(parameterType, this);
}
if (inst.OpCode == OpCode.NewObj) {
rr = new ResolveResult(cecilMapper.GetType(inst.Method.DeclaringType));
} else {
rr = new ResolveResult(cecilMapper.GetType(inst.Method.ReturnType));
}
} }
var argumentResolveResults = arguments.Skip(firstParamIndex).Select(arg => arg.ResolveResult).ToList();
var rr = new CSharpInvocationResolveResult(target.ResolveResult, inst.Method, argumentResolveResults);
var argumentExpressions = arguments.Skip(firstParamIndex).Select(arg => arg.Expression); var argumentExpressions = arguments.Skip(firstParamIndex).Select(arg => arg.Expression);
if (inst.OpCode == OpCode.NewObj) { if (inst.OpCode == OpCode.NewObj) {
@ -435,19 +406,18 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj(LdObj inst) protected internal override TranslatedExpression VisitLdObj(LdObj inst)
{ {
var target = Translate(inst.Target); var target = Translate(inst.Target);
var type = cecilMapper.GetType(inst.Type); if (target.Type.Equals(new ByReferenceType(inst.Type)) && target.Expression is DirectionExpression) {
if (target.Type.Equals(new ByReferenceType(type)) && target.Expression is DirectionExpression) {
// we can deference the managed reference by stripping away the 'ref' // we can deference the managed reference by stripping away the 'ref'
var result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression); var result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression);
result = result.ConvertTo(type, this); result = result.ConvertTo(inst.Type, this);
result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation result.Expression.AddAnnotation(inst); // add LdObj in addition to the existing ILInstruction annotation
return result; return result;
} else { } else {
// Cast pointer type if necessary: // Cast pointer type if necessary:
target = target.ConvertTo(new PointerType(type), this); target = target.ConvertTo(new PointerType(inst.Type), this);
return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) return new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ResolveResult(type)); .WithRR(new ResolveResult(inst.Type));
} }
} }
@ -455,17 +425,16 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
var target = Translate(inst.Target); var target = Translate(inst.Target);
var value = Translate(inst.Value); var value = Translate(inst.Value);
var type = cecilMapper.GetType(inst.Type);
TranslatedExpression result; TranslatedExpression result;
if (target.Type.Equals(new ByReferenceType(type)) && target.Expression is DirectionExpression) { if (target.Type.Equals(new ByReferenceType(inst.Type)) && target.Expression is DirectionExpression) {
// we can deference the managed reference by stripping away the 'ref' // we can deference the managed reference by stripping away the 'ref'
result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression); result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression);
} else { } else {
// Cast pointer type if necessary: // Cast pointer type if necessary:
target = target.ConvertTo(new PointerType(type), this); target = target.ConvertTo(new PointerType(inst.Type), this);
result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression) result = new UnaryOperatorExpression(UnaryOperatorType.Dereference, target.Expression)
.WithoutILInstruction() .WithoutILInstruction()
.WithRR(new ResolveResult(type)); .WithRR(new ResolveResult(inst.Type));
} }
return Assignment(result, value).WithILInstruction(inst); return Assignment(result, value).WithILInstruction(inst);
} }
@ -479,7 +448,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
return new CastExpression(ConvertType(inst.Type), arg.Expression) return new CastExpression(ConvertType(inst.Type), arg.Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ConversionResolveResult(cecilMapper.GetType(inst.Type), arg.ResolveResult, Conversion.UnboxingConversion)); .WithRR(new ConversionResolveResult(inst.Type, arg.ResolveResult, Conversion.UnboxingConversion));
} }
protected override TranslatedExpression Default(ILInstruction inst) protected override TranslatedExpression Default(ILInstruction inst)

116
ICSharpCode.Decompiler/CSharp/NRefactoryCecilMapper.cs

@ -1,116 +0,0 @@
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Mono.Cecil;
namespace ICSharpCode.Decompiler.CSharp
{
/// <summary>
/// Maps from cecil types to NRefactory and vice versa.
/// </summary>
class NRefactoryCecilMapper
{
readonly ITypeResolveContext context;
readonly CecilLoader cecilLoader = new CecilLoader();
readonly Func<IUnresolvedEntity, MemberReference> nr2cecilLookup;
/// <param name="compilation">Compilation to use for Cecil-&gt;NRefactory lookups</param>
/// <param name="module">Compilation to use for Cecil-&gt;NRefactory lookups</param>
/// <param name = "nr2cecilLookup">NRefactory-&gt;Cecil lookup function</param>
internal NRefactoryCecilMapper(ICompilation compilation, ModuleDefinition module, Func<IUnresolvedEntity, MemberReference> nr2cecilLookup)
{
this.nr2cecilLookup = nr2cecilLookup;
this.context = new SimpleTypeResolveContext(compilation.MainAssembly);
this.cecilLoader.SetCurrentModule(module);
}
public MemberReference GetCecil(IMember member)
{
if (member == null)
return null;
return nr2cecilLookup(member.UnresolvedMember);
}
public MemberReference GetCecil(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return null;
return nr2cecilLookup(typeDefinition.Parts[0]);
}
/// <summary>
/// Retrieves a type definition for a type defined in the compilation's main assembly.
/// </summary>
public IType GetType(TypeReference typeReference)
{
if (typeReference == null)
return SpecialType.UnknownType;
var typeRef = cecilLoader.ReadTypeReference(typeReference);
return typeRef.Resolve(context);
}
public IMethod GetMethod(MethodReference methodReference)
{
var method = GetNonGenericMethod(methodReference.GetElementMethod());
// TODO: specialize the method
return method;
}
IMethod GetNonGenericMethod(MethodReference methodReference)
{
ITypeDefinition typeDef = GetType(methodReference.DeclaringType).GetDefinition();
if (typeDef == null)
return null;
IEnumerable<IMethod> methods;
if (methodReference.Name == ".ctor") {
methods = typeDef.GetConstructors();
} else if (methodReference.Name == ".cctor") {
return typeDef.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
} else {
methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)
.Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers));
}
foreach (var method in methods) {
if (GetCecil(method) == methodReference)
return method;
}
var parameterTypes = methodReference.Parameters.SelectArray(p => GetType(p.ParameterType));
foreach (var method in methods) {
if (parameterTypes.Length == method.Parameters.Count) {
bool signatureMatches = true;
for (int i = 0; i < parameterTypes.Length; i++) {
IType type1 = DummyTypeParameter.NormalizeAllTypeParameters(parameterTypes[i]);
IType type2 = DummyTypeParameter.NormalizeAllTypeParameters(method.Parameters[i].Type);
if (!type1.Equals(type2)) {
signatureMatches = false;
break;
}
}
if (signatureMatches)
return method;
}
}
return null;
}
}
}

4
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -32,9 +32,9 @@ namespace ICSharpCode.Decompiler.CSharp
readonly ExpressionBuilder exprBuilder; readonly ExpressionBuilder exprBuilder;
readonly IMethod currentMethod; readonly IMethod currentMethod;
public StatementBuilder(IMethod method, NRefactoryCecilMapper cecilMapper) public StatementBuilder(IMethod method)
{ {
this.exprBuilder = new ExpressionBuilder(method.Compilation, cecilMapper); this.exprBuilder = new ExpressionBuilder(method.Compilation);
this.currentMethod = method; this.currentMethod = method;
} }

4
ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs

@ -234,12 +234,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
#endregion #endregion
public void Run(AstNode node, TransformContext context) public void Run(AstNode node)
{ {
BlockStatement block = node as BlockStatement; BlockStatement block = node as BlockStatement;
if (block == null) { if (block == null) {
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
Run(child, context); Run(child);
} }
} else { } else {
Result r = GetResultFromBlock(block); Result r = GetResultFromBlock(block);

38
ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs

@ -30,16 +30,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// <summary> /// <summary>
/// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer. /// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer.
/// </summary> /// </summary>
public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<TransformContext, object>, IAstTransform public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor, IAstTransform
{ {
public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, TransformContext context) readonly DecompilerTypeSystem typeSystem;
public ConvertConstructorCallIntoInitializer(DecompilerTypeSystem typeSystem)
{
if (typeSystem == null)
throw new ArgumentNullException("typeSystem");
this.typeSystem = typeSystem;
}
public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
{ {
ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement; ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;
if (stmt == null) if (stmt == null)
return null; return;
InvocationExpression invocation = stmt.Expression as InvocationExpression; InvocationExpression invocation = stmt.Expression as InvocationExpression;
if (invocation == null) if (invocation == null)
return null; return;
MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression; MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
if (mre != null && mre.MemberName == ".ctor") { if (mre != null && mre.MemberName == ".ctor") {
ConstructorInitializer ci = new ConstructorInitializer(); ConstructorInitializer ci = new ConstructorInitializer();
@ -48,7 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
else if (mre.Target is BaseReferenceExpression) else if (mre.Target is BaseReferenceExpression)
ci.ConstructorInitializerType = ConstructorInitializerType.Base; ci.ConstructorInitializerType = ConstructorInitializerType.Base;
else else
return null; return;
// Move arguments from invocation to initializer: // Move arguments from invocation to initializer:
invocation.Arguments.MoveTo(ci.Arguments); invocation.Arguments.MoveTo(ci.Arguments);
// Add the initializer: (unless it is the default 'base()') // Add the initializer: (unless it is the default 'base()')
@ -57,7 +66,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// Remove the statement: // Remove the statement:
stmt.Remove(); stmt.Remove();
} }
return null;
} }
static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement { static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement {
@ -73,21 +81,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode()))); static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode())));
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, TransformContext context) public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{ {
// Handle initializers on instance fields // Handle initializers on instance fields
HandleInstanceFieldInitializers(typeDeclaration.Members); HandleInstanceFieldInitializers(typeDeclaration.Members);
// Now convert base constructor calls to initializers: // Now convert base constructor calls to initializers:
base.VisitTypeDeclaration(typeDeclaration, context); base.VisitTypeDeclaration(typeDeclaration);
// Remove single empty constructor: // Remove single empty constructor:
RemoveSingleEmptyConstructor(typeDeclaration); RemoveSingleEmptyConstructor(typeDeclaration);
// Handle initializers on static fields: // Handle initializers on static fields:
HandleStaticFieldInitializers(typeDeclaration.Members, context); HandleStaticFieldInitializers(typeDeclaration.Members);
return null;
} }
void HandleInstanceFieldInitializers(IEnumerable<AstNode> members) void HandleInstanceFieldInitializers(IEnumerable<AstNode> members)
@ -144,13 +150,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
void HandleStaticFieldInitializers(IEnumerable<AstNode> members, TransformContext context) void HandleStaticFieldInitializers(IEnumerable<AstNode> members)
{ {
// Translate static constructor into field initializers if the class is BeforeFieldInit // Translate static constructor into field initializers if the class is BeforeFieldInit
var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);
if (staticCtor != null) { if (staticCtor != null) {
IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; IMethod ctorMethod = staticCtor.GetSymbol() as IMethod;
MethodDefinition ctorMethodDef = context.CecilMapper.GetCecil(ctorMethod) as MethodDefinition; MethodDefinition ctorMethodDef = typeSystem.GetCecil(ctorMethod) as MethodDefinition;
if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) { if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) {
while (true) { while (true) {
ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
@ -174,14 +180,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
void IAstTransform.Run(AstNode node, TransformContext context) public void Run(AstNode node)
{ {
// If we're viewing some set of members (fields are direct children of CompilationUnit), // If we're viewing some set of members (fields are direct children of CompilationUnit),
// we also need to handle those: // we also need to handle those:
HandleInstanceFieldInitializers(node.Children); HandleInstanceFieldInitializers(node.Children);
HandleStaticFieldInitializers(node.Children, context); HandleStaticFieldInitializers(node.Children);
node.AcceptVisitor(this, context); node.AcceptVisitor(this);
} }
} }
} }

14
ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs

@ -25,18 +25,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
public interface IAstTransform public interface IAstTransform
{ {
void Run(AstNode rootNode, TransformContext context); void Run(AstNode rootNode);
}
public class TransformContext
{
internal readonly NRefactoryCecilMapper CecilMapper;
public readonly ICompilation Compilation;
internal TransformContext(ICompilation compilation, NRefactoryCecilMapper cecilMapper)
{
this.Compilation = compilation;
this.CecilMapper = cecilMapper;
}
} }
} }

30
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

@ -21,22 +21,22 @@ using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.Decompiler.CSharp.Transforms namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
public class IntroduceUnsafeModifier : DepthFirstAstVisitor<object, bool>, IAstTransform public class IntroduceUnsafeModifier : DepthFirstAstVisitor<bool>, IAstTransform
{ {
public static readonly object PointerArithmeticAnnotation = new PointerArithmetic(); public static readonly object PointerArithmeticAnnotation = new PointerArithmetic();
sealed class PointerArithmetic {} sealed class PointerArithmetic {}
public void Run(AstNode compilationUnit, TransformContext context) public void Run(AstNode compilationUnit)
{ {
compilationUnit.AcceptVisitor(this, null); compilationUnit.AcceptVisitor(this);
} }
protected override bool VisitChildren(AstNode node, object data) protected override bool VisitChildren(AstNode node)
{ {
bool result = false; bool result = false;
for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
result |= child.AcceptVisitor(this, data); result |= child.AcceptVisitor(this);
} }
if (result && node is EntityDeclaration && !(node is Accessor)) { if (result && node is EntityDeclaration && !(node is Accessor)) {
((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe; ((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe;
@ -45,23 +45,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return result; return result;
} }
public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression)
{ {
base.VisitPointerReferenceExpression(pointerReferenceExpression, data); base.VisitPointerReferenceExpression(pointerReferenceExpression);
return true; return true;
} }
public override bool VisitComposedType(ComposedType composedType, object data) public override bool VisitComposedType(ComposedType composedType)
{ {
if (composedType.PointerRank > 0) if (composedType.PointerRank > 0)
return true; return true;
else else
return base.VisitComposedType(composedType, data); return base.VisitComposedType(composedType);
} }
public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression)
{ {
bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression, data); bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression);
if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) { if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) {
BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression; BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) { if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) {
@ -81,9 +81,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression)
{ {
bool result = base.VisitMemberReferenceExpression(memberReferenceExpression, data); bool result = base.VisitMemberReferenceExpression(memberReferenceExpression);
UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression; UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression;
if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) { if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) {
PointerReferenceExpression pre = new PointerReferenceExpression(); PointerReferenceExpression pre = new PointerReferenceExpression();
@ -97,9 +97,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return result; return result;
} }
public override bool VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) public override bool VisitStackAllocExpression(StackAllocExpression stackAllocExpression)
{ {
base.VisitStackAllocExpression(stackAllocExpression, data); base.VisitStackAllocExpression(stackAllocExpression);
return true; return true;
} }
} }

21
ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// Replaces method calls with the appropriate operator expressions. /// Replaces method calls with the appropriate operator expressions.
/// Also simplifies "x = x op y" into "x op= y" where possible. /// Also simplifies "x = x op y" into "x op= y" where possible.
/// </summary> /// </summary>
public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>, IAstTransform public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor, IAstTransform
{ {
static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression { static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression {
Target = new Choice { Target = new Choice {
@ -41,11 +41,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
MemberName = "TypeHandle" MemberName = "TypeHandle"
}; };
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) public override void VisitInvocationExpression(InvocationExpression invocationExpression)
{ {
base.VisitInvocationExpression(invocationExpression, data); base.VisitInvocationExpression(invocationExpression);
ProcessInvocationExpression(invocationExpression); ProcessInvocationExpression(invocationExpression);
return null;
} }
internal static void ProcessInvocationExpression(InvocationExpression invocationExpression) internal static void ProcessInvocationExpression(InvocationExpression invocationExpression)
@ -232,9 +231,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
public override object VisitAssignmentExpression(AssignmentExpression assignment, object data) public override void VisitAssignmentExpression(AssignmentExpression assignment)
{ {
base.VisitAssignmentExpression(assignment, data); base.VisitAssignmentExpression(assignment);
// Combine "x = x op y" into "x op= y" // Combine "x = x op y" into "x op= y"
BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression; BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) { if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) {
@ -265,7 +264,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
} }
return null;
} }
public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop) public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop)
@ -330,9 +328,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return new SimpleType(parameterType.Name); return new SimpleType(parameterType.Name);
} }
public override object VisitCastExpression(CastExpression castExpression, object data) public override void VisitCastExpression(CastExpression castExpression)
{ {
base.VisitCastExpression(castExpression, data); base.VisitCastExpression(castExpression);
// Handle methodof // Handle methodof
Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression); Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression);
if (m.Success) { if (m.Success) {
@ -345,12 +343,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
castExpression.ReplaceWith(m.Get<AstNode>("ldtokenNode").Single()); castExpression.ReplaceWith(m.Get<AstNode>("ldtokenNode").Single());
} }
return null;
} }
void IAstTransform.Run(AstNode node, TransformContext context) void IAstTransform.Run(AstNode node)
{ {
node.AcceptVisitor(this, null); node.AcceptVisitor(this);
} }
} }
} }

296
ICSharpCode.Decompiler/DecompilerTypeSystem.cs

@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Mono.Cecil;
namespace ICSharpCode.Decompiler
{
/// <summary>
/// Manages the NRefactory type system for the decompiler.
/// This class is thread-safe.
/// </summary>
public class DecompilerTypeSystem
{
readonly ModuleDefinition moduleDefinition;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
/// <summary>
/// CecilLoader used for converting cecil type references to ITypeReference.
/// May only be accessed within lock(cecilLoader).
/// </summary>
CecilLoader typeReferenceCecilLoader = new CecilLoader();
/// <summary>
/// Dictionary for NRefactory->Cecil lookup. Only contains entities from the main module.
/// May only be accessed within lock(entityDict)
/// </summary>
Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>();
Dictionary<FieldReference, IField> fieldLookupCache = new Dictionary<FieldReference, IField>();
Dictionary<MethodReference, IMethod> methodLookupCache = new Dictionary<MethodReference, IMethod>();
public DecompilerTypeSystem(ModuleDefinition moduleDefinition)
{
if (moduleDefinition == null)
throw new ArgumentNullException("moduleDefinition");
this.moduleDefinition = moduleDefinition;
CecilLoader mainAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference };
CecilLoader referencedAssemblyCecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true };
typeReferenceCecilLoader.SetCurrentModule(moduleDefinition);
IUnresolvedAssembly mainAssembly = mainAssemblyCecilLoader.LoadModule(moduleDefinition);
var referencedAssemblies = new List<IUnresolvedAssembly>();
foreach (var asmRef in moduleDefinition.AssemblyReferences) {
var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef);
if (asm != null)
referencedAssemblies.Add(referencedAssemblyCecilLoader.LoadAssembly(asm));
}
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
context = new SimpleTypeResolveContext(compilation.MainAssembly);
}
public ICompilation Compilation
{
get { return compilation; }
}
public ModuleDefinition ModuleDefinition
{
get { return moduleDefinition; }
}
void StoreMemberReference(IUnresolvedEntity entity, MemberReference mr)
{
// This is a callback from the type system, which is multi-threaded and may be accessed externally
lock (entityDict)
entityDict[entity] = mr;
}
MemberReference GetCecil(IUnresolvedEntity member)
{
lock (entityDict) {
MemberReference mr;
if (member != null && entityDict.TryGetValue(member, out mr))
return mr;
return null;
}
}
/// <summary>
/// Retrieves the Cecil member definition for the specified member.
/// </summary>
/// <remarks>
/// Returns null if the member is not defined in the module being decompiled.
/// </remarks>
public MemberReference GetCecil(IMember member)
{
if (member == null)
return null;
return GetCecil(member.UnresolvedMember);
}
/// <summary>
/// Retrieves the Cecil type definition.
/// </summary>
/// <remarks>
/// Returns null if the type is not defined in the module being decompiled.
/// </remarks>
public TypeDefinition GetCecil(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return null;
return GetCecil(typeDefinition.Parts[0]) as TypeDefinition;
}
#region Resolve Type
/// <summary>
/// Retrieves a type definition for a type defined in the compilation's main assembly.
/// </summary>
public IType GetType(TypeReference typeReference)
{
if (typeReference == null)
return SpecialType.UnknownType;
ITypeReference typeRef;
lock (typeReferenceCecilLoader)
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference);
return typeRef.Resolve(context);
}
#endregion
#region Resolve Field
public IField GetField(FieldReference fieldReference)
{
if (fieldReference == null)
throw new ArgumentNullException("fieldReference");
lock (fieldLookupCache) {
IField field;
if (!fieldLookupCache.TryGetValue(fieldReference, out field)) {
field = GetNonGenericField(fieldReference);
// TODO: specialize the field if necessary
fieldLookupCache[fieldReference] = field;
}
return field;
}
}
IField GetNonGenericField(FieldReference fieldReference)
{
Debug.Assert(Monitor.IsEntered(fieldLookupCache));
IField field;
if (!fieldLookupCache.TryGetValue(fieldReference, out field)) {
field = FindNonGenericField(fieldReference);
fieldLookupCache.Add(fieldReference, field);
}
return field;
}
IField FindNonGenericField(FieldReference fieldReference)
{
ITypeDefinition typeDef = GetType(fieldReference.DeclaringType).GetDefinition();
if (typeDef == null)
return CreateFakeField(fieldReference);
foreach (IField field in typeDef.Fields)
if (field.Name == fieldReference.Name)
return field;
return CreateFakeField(fieldReference);
}
IField CreateFakeField(FieldReference fieldReference)
{
var declaringType = GetType(fieldReference.DeclaringType);
var f = new DefaultUnresolvedField();
f.Name = fieldReference.Name;
f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType);
return new ResolvedFakeField(f, context, declaringType);
}
class ResolvedFakeField : DefaultResolvedField
{
readonly IType declaringType;
public ResolvedFakeField(DefaultUnresolvedField unresolved, ITypeResolveContext parentContext, IType declaringType)
: base(unresolved, parentContext)
{
this.declaringType = declaringType;
}
public override IType DeclaringType
{
get { return declaringType; }
}
}
#endregion
#region Resolve Method
public IMethod GetMethod(MethodReference methodReference)
{
if (methodReference == null)
throw new ArgumentNullException("methodReference");
lock (methodLookupCache) {
IMethod method;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
method = GetNonGenericMethod(methodReference.GetElementMethod());
// TODO: specialize the method
methodLookupCache[methodReference] = method;
}
return method;
}
}
IMethod GetNonGenericMethod(MethodReference methodReference)
{
Debug.Assert(Monitor.IsEntered(methodLookupCache));
IMethod method;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
method = FindNonGenericMethod(methodReference);
methodLookupCache.Add(methodReference, method);
}
return method;
}
IMethod FindNonGenericMethod(MethodReference methodReference)
{
ITypeDefinition typeDef = GetType(methodReference.DeclaringType).GetDefinition();
if (typeDef == null)
return CreateFakeMethod(methodReference);
IEnumerable<IMethod> methods;
if (methodReference.Name == ".ctor") {
methods = typeDef.GetConstructors();
} else if (methodReference.Name == ".cctor") {
return typeDef.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic);
} else {
methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)
.Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers));
}
foreach (var method in methods) {
if (GetCecil(method) == methodReference)
return method;
}
var parameterTypes = methodReference.Parameters.SelectArray(p => GetType(p.ParameterType));
foreach (var method in methods) {
if (CompareSignatures(method.Parameters, parameterTypes))
return method;
}
return CreateFakeMethod(methodReference);
}
static bool CompareSignatures(IList<IParameter> parameters, IType[] parameterTypes)
{
if (parameterTypes.Length != parameters.Count)
return false;
for (int i = 0; i < parameterTypes.Length; i++) {
IType type1 = DummyTypeParameter.NormalizeAllTypeParameters(parameterTypes[i]);
IType type2 = DummyTypeParameter.NormalizeAllTypeParameters(parameters[i].Type);
if (!type1.Equals(type2)) {
return false;
}
}
return true;
}
/// <summary>
/// Create a dummy IMethod from the specified MethodReference
/// </summary>
IMethod CreateFakeMethod(MethodReference methodReference)
{
var declaringTypeReference = typeReferenceCecilLoader.ReadTypeReference(methodReference.DeclaringType);
var m = new DefaultUnresolvedMethod();
if (methodReference.Name == ".ctor" || methodReference.Name == ".cctor")
m.SymbolKind = SymbolKind.Constructor;
m.Name = methodReference.Name;
m.ReturnType = typeReferenceCecilLoader.ReadTypeReference(methodReference.ReturnType);
m.IsStatic = !methodReference.HasThis;
for (int i = 0; i < methodReference.GenericParameters.Count; i++) {
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, methodReference.GenericParameters[i].Name));
}
foreach (var p in methodReference.Parameters) {
m.Parameters.Add(new DefaultUnresolvedParameter(typeReferenceCecilLoader.ReadTypeReference(p.ParameterType), p.Name));
}
return new ResolvedFakeMethod(m, context, declaringTypeReference.Resolve(context));
}
class ResolvedFakeMethod : DefaultResolvedMethod
{
readonly IType declaringType;
public ResolvedFakeMethod(DefaultUnresolvedMethod unresolved, ITypeResolveContext parentContext, IType declaringType)
: base(unresolved, parentContext)
{
this.declaringType = declaringType;
}
public override IType DeclaringType
{
get { return declaringType; }
}
}
#endregion
}
}

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -64,7 +64,6 @@
<ItemGroup> <ItemGroup>
<Compile Include="CSharp\Annotations.cs" /> <Compile Include="CSharp\Annotations.cs" />
<Compile Include="CSharp\TranslatedExpression.cs" /> <Compile Include="CSharp\TranslatedExpression.cs" />
<Compile Include="CSharp\NRefactoryCecilMapper.cs" />
<Compile Include="CSharp\CSharpDecompiler.cs" /> <Compile Include="CSharp\CSharpDecompiler.cs" />
<Compile Include="CSharp\ExpressionBuilder.cs" /> <Compile Include="CSharp\ExpressionBuilder.cs" />
<Compile Include="CSharp\NRefactoryExtensions.cs" /> <Compile Include="CSharp\NRefactoryExtensions.cs" />
@ -75,6 +74,7 @@
<Compile Include="CSharp\Transforms\IAstTransform.cs" /> <Compile Include="CSharp\Transforms\IAstTransform.cs" />
<Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" /> <Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" />
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" /> <Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="DecompilerTypeSystem.cs" />
<Compile Include="IL\Instructions.cs"> <Compile Include="IL\Instructions.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>

8
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -30,10 +30,14 @@ namespace ICSharpCode.Decompiler.IL
class BlockBuilder class BlockBuilder
{ {
readonly Mono.Cecil.Cil.MethodBody body; readonly Mono.Cecil.Cil.MethodBody body;
readonly DecompilerTypeSystem typeSystem;
public BlockBuilder(Mono.Cecil.Cil.MethodBody body) public BlockBuilder(Mono.Cecil.Cil.MethodBody body, DecompilerTypeSystem typeSystem)
{ {
Debug.Assert(body != null);
Debug.Assert(typeSystem != null);
this.body = body; this.body = body;
this.typeSystem = typeSystem;
} }
List<TryInstruction> tryInstructionList = new List<TryInstruction>(); List<TryInstruction> tryInstructionList = new List<TryInstruction>();
@ -68,7 +72,7 @@ namespace ICSharpCode.Decompiler.IL
tryInstructionList.Add(tryCatch); tryInstructionList.Add(tryCatch);
} }
var variable = new ILVariable(VariableKind.Exception, eh.CatchType, handlerBlock.ILRange.Start); var variable = new ILVariable(VariableKind.Exception, typeSystem.GetType(eh.CatchType), handlerBlock.ILRange.Start);
variable.Name = "ex"; variable.Name = "ex";
handlerBlock.EntryPoint.Instructions.Add(new LdLoc(variable)); handlerBlock.EntryPoint.Instructions.Add(new LdLoc(variable));

179
ICSharpCode.Decompiler/IL/ILReader.cs

@ -23,6 +23,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
using Cil = Mono.Cecil.Cil; using Cil = Mono.Cecil.Cil;
using System.Collections; using System.Collections;
@ -46,9 +47,18 @@ namespace ICSharpCode.Decompiler.IL
return new MetadataToken(reader.ReadUInt32()); return new MetadataToken(reader.ReadUInt32());
} }
Cil.MethodBody body; readonly ICompilation compilation;
TypeSystem typeSystem; readonly DecompilerTypeSystem typeSystem;
public ILReader(DecompilerTypeSystem typeSystem)
{
if (typeSystem == null)
throw new ArgumentNullException("typeSystem");
this.typeSystem = typeSystem;
this.compilation = typeSystem.Compilation;
}
Cil.MethodBody body;
BlobReader reader; BlobReader reader;
Stack<StackType> stack; Stack<StackType> stack;
ILVariable[] parameterVariables; ILVariable[] parameterVariables;
@ -64,11 +74,10 @@ namespace ICSharpCode.Decompiler.IL
if (body == null) if (body == null)
throw new ArgumentNullException("body"); throw new ArgumentNullException("body");
this.body = body; this.body = body;
this.typeSystem = body.Method.Module.TypeSystem;
this.reader = body.GetILReader(); this.reader = body.GetILReader();
this.stack = new Stack<StackType>(body.MaxStackSize); this.stack = new Stack<StackType>(body.MaxStackSize);
this.parameterVariables = InitParameterVariables(body); InitParameterVariables();
this.localVariables = body.Variables.Select(v => new ILVariable(v)).ToArray(); this.localVariables = body.Variables.SelectArray(CreateILVariable);
this.instructionBuilder = new List<ILInstruction>(); this.instructionBuilder = new List<ILInstruction>();
this.isBranchTarget = new BitArray(body.CodeSize); this.isBranchTarget = new BitArray(body.CodeSize);
this.branchStackDict = new Dictionary<int, ImmutableArray<StackType>>(); this.branchStackDict = new Dictionary<int, ImmutableArray<StackType>>();
@ -80,18 +89,66 @@ namespace ICSharpCode.Decompiler.IL
return body.LookupToken(token); return body.LookupToken(token);
} }
static ILVariable[] InitParameterVariables(Mono.Cecil.Cil.MethodBody body) IType ReadAndDecodeTypeReference()
{
var token = ReadMetadataToken(ref reader);
var typeReference = body.LookupToken(token) as TypeReference;
return typeSystem.GetType(typeReference);
}
IMethod ReadAndDecodeMethodReference()
{
var token = ReadMetadataToken(ref reader);
var methodReference = body.LookupToken(token) as MethodReference;
return typeSystem.GetMethod(methodReference);
}
IField ReadAndDecodeFieldReference()
{
var token = ReadMetadataToken(ref reader);
var fieldReference = body.LookupToken(token) as FieldReference;
return typeSystem.GetField(fieldReference);
}
void InitParameterVariables()
{ {
var parameterVariables = new ILVariable[body.Method.GetPopAmount()]; parameterVariables = new ILVariable[GetPopCount(OpCode.Call, body.Method)];
int paramIndex = 0; int paramIndex = 0;
if (body.Method.HasThis) if (body.Method.HasThis)
parameterVariables[paramIndex++] = new ILVariable(body.ThisParameter); parameterVariables[paramIndex++] = CreateILVariable(body.ThisParameter);
foreach (var p in body.Method.Parameters) foreach (var p in body.Method.Parameters)
parameterVariables[paramIndex++] = new ILVariable(p); parameterVariables[paramIndex++] = CreateILVariable(p);
Debug.Assert(paramIndex == parameterVariables.Length); Debug.Assert(paramIndex == parameterVariables.Length);
return parameterVariables;
} }
ILVariable CreateILVariable(Cil.VariableDefinition v)
{
var ilVar = new ILVariable(VariableKind.Local, typeSystem.GetType(v.VariableType), v.Index);
if (string.IsNullOrEmpty(v.Name))
ilVar.Name = "V_" + v.Index;
else
ilVar.Name = v.Name;
return ilVar;
}
ILVariable CreateILVariable(ParameterDefinition p)
{
var variableKind = p.Index == -1 ? VariableKind.This : VariableKind.Parameter;
var ilVar = new ILVariable(variableKind, typeSystem.GetType(p.ParameterType), p.Index);
ilVar.StoreCount = 1; // count the initial store when the method is called with an argument
if (variableKind == VariableKind.This)
ilVar.Name = "this";
else if (string.IsNullOrEmpty(p.Name))
ilVar.Name = "P_" + p.Index;
else
ilVar.Name = p.Name;
return ilVar;
}
/// <summary>
/// Warn when invalid IL is detected.
/// ILSpy should be able to handle invalid IL; but this method can be helpful for debugging the ILReader, as this method should not get called when processing valid IL.
/// </summary>
void Warn(string message) void Warn(string message)
{ {
Debug.Fail(message); Debug.Fail(message);
@ -120,6 +177,8 @@ namespace ICSharpCode.Decompiler.IL
if (outputStacks != null) if (outputStacks != null)
outputStacks.Add(start, stack.ToImmutableArray()); outputStacks.Add(start, stack.ToImmutableArray());
ILInstruction decodedInstruction = DecodeInstruction(); ILInstruction decodedInstruction = DecodeInstruction();
if (decodedInstruction.ResultType == StackType.Unknown)
Warn("Unknown result type (might be due to invalid IL)");
decodedInstruction.CheckInvariant(); decodedInstruction.CheckInvariant();
if (decodedInstruction.ResultType != StackType.Void) if (decodedInstruction.ResultType != StackType.Void)
stack.Push(decodedInstruction.ResultType); stack.Push(decodedInstruction.ResultType);
@ -176,7 +235,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
Init(body); Init(body);
ReadInstructions(null, cancellationToken); ReadInstructions(null, cancellationToken);
var container = new BlockBuilder(body).CreateBlocks(instructionBuilder, isBranchTarget); var container = new BlockBuilder(body, typeSystem).CreateBlocks(instructionBuilder, isBranchTarget);
var function = new ILFunction(body.Method, container); var function = new ILFunction(body.Method, container);
function.Variables.AddRange(parameterVariables); function.Variables.AddRange(parameterVariables);
function.Variables.AddRange(localVariables); function.Variables.AddRange(localVariables);
@ -416,29 +475,29 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldstr: case ILOpCode.Ldstr:
return DecodeLdstr(); return DecodeLdstr();
case ILOpCode.Ldftn: case ILOpCode.Ldftn:
return new LdFtn((MethodReference)ReadAndDecodeMetadataToken()); return new LdFtn(ReadAndDecodeMethodReference());
case ILOpCode.Ldind_I1: case ILOpCode.Ldind_I1:
return new LdObj(Pop(), typeSystem.SByte); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.SByte));
case ILOpCode.Ldind_I2: case ILOpCode.Ldind_I2:
return new LdObj(Pop(), typeSystem.Int16); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int16));
case ILOpCode.Ldind_I4: case ILOpCode.Ldind_I4:
return new LdObj(Pop(), typeSystem.Int32); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int32));
case ILOpCode.Ldind_I8: case ILOpCode.Ldind_I8:
return new LdObj(Pop(), typeSystem.Int64); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int64));
case ILOpCode.Ldind_U1: case ILOpCode.Ldind_U1:
return new LdObj(Pop(), typeSystem.Byte); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Byte));
case ILOpCode.Ldind_U2: case ILOpCode.Ldind_U2:
return new LdObj(Pop(), typeSystem.UInt16); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.UInt16));
case ILOpCode.Ldind_U4: case ILOpCode.Ldind_U4:
return new LdObj(Pop(), typeSystem.UInt32); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.UInt32));
case ILOpCode.Ldind_R4: case ILOpCode.Ldind_R4:
return new LdObj(Pop(), typeSystem.Single); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Single));
case ILOpCode.Ldind_R8: case ILOpCode.Ldind_R8:
return new LdObj(Pop(), typeSystem.Double); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Double));
case ILOpCode.Ldind_I: case ILOpCode.Ldind_I:
return new LdObj(Pop(), typeSystem.IntPtr); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.IntPtr));
case ILOpCode.Ldind_Ref: case ILOpCode.Ldind_Ref:
return new LdObj(Pop(), typeSystem.Object); return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Object));
case ILOpCode.Ldloc: case ILOpCode.Ldloc:
return Ldloc(reader.ReadUInt16()); return Ldloc(reader.ReadUInt16());
case ILOpCode.Ldloc_S: case ILOpCode.Ldloc_S:
@ -493,21 +552,21 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Starg_S: case ILOpCode.Starg_S:
return Starg(reader.ReadByte()); return Starg(reader.ReadByte());
case ILOpCode.Stind_I1: case ILOpCode.Stind_I1:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.SByte)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.SByte)));
case ILOpCode.Stind_I2: case ILOpCode.Stind_I2:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Int16)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Int16)));
case ILOpCode.Stind_I4: case ILOpCode.Stind_I4:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Int32)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Int32)));
case ILOpCode.Stind_I8: case ILOpCode.Stind_I8:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Int64)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Int64)));
case ILOpCode.Stind_R4: case ILOpCode.Stind_R4:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Single)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Single)));
case ILOpCode.Stind_R8: case ILOpCode.Stind_R8:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Double)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Double)));
case ILOpCode.Stind_I: case ILOpCode.Stind_I:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.IntPtr)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.IntPtr)));
case ILOpCode.Stind_Ref: case ILOpCode.Stind_Ref:
return new Void(new StObj(value: Pop(), target: Pop(), type: typeSystem.Object)); return new Void(new StObj(value: Pop(), target: Pop(), type: compilation.FindType(KnownTypeCode.Object)));
case ILOpCode.Stloc: case ILOpCode.Stloc:
return Stloc(reader.ReadUInt16()); return Stloc(reader.ReadUInt16());
case ILOpCode.Stloc_S: case ILOpCode.Stloc_S:
@ -528,19 +587,19 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Xor: case ILOpCode.Xor:
return BinaryNumeric(OpCode.BitXor); return BinaryNumeric(OpCode.BitXor);
case ILOpCode.Box: case ILOpCode.Box:
return new Box(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new Box(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Castclass: case ILOpCode.Castclass:
return new CastClass(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new CastClass(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Cpobj: case ILOpCode.Cpobj:
{ {
var type = (TypeReference)ReadAndDecodeMetadataToken(); var type = ReadAndDecodeTypeReference();
var ld = new LdObj(Pop(), type); var ld = new LdObj(Pop(), type);
return new Void(new StObj(Pop(), ld, type)); return new Void(new StObj(Pop(), ld, type));
} }
case ILOpCode.Initobj: case ILOpCode.Initobj:
return new InitObj(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new InitObj(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Isinst: case ILOpCode.Isinst:
return new IsInst(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new IsInst(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Ldelem: case ILOpCode.Ldelem:
case ILOpCode.Ldelem_I1: case ILOpCode.Ldelem_I1:
case ILOpCode.Ldelem_I2: case ILOpCode.Ldelem_I2:
@ -555,27 +614,27 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldelem_Ref: case ILOpCode.Ldelem_Ref:
throw new NotImplementedException(); throw new NotImplementedException();
case ILOpCode.Ldelema: case ILOpCode.Ldelema:
return new LdElema(index: Pop(), array: Pop(), type: (TypeReference)ReadAndDecodeMetadataToken()); return new LdElema(index: Pop(), array: Pop(), type: ReadAndDecodeTypeReference());
case ILOpCode.Ldfld: case ILOpCode.Ldfld:
return new LdFld(Pop(), (FieldReference)ReadAndDecodeMetadataToken()); return new LdFld(Pop(), ReadAndDecodeFieldReference());
case ILOpCode.Ldflda: case ILOpCode.Ldflda:
return new LdFlda(Pop(), (FieldReference)ReadAndDecodeMetadataToken()); return new LdFlda(Pop(), ReadAndDecodeFieldReference());
case ILOpCode.Stfld: case ILOpCode.Stfld:
return new Void(new StFld(value: Pop(), target: Pop(), field: (FieldReference)ReadAndDecodeMetadataToken())); return new Void(new StFld(value: Pop(), target: Pop(), field: ReadAndDecodeFieldReference()));
case ILOpCode.Ldlen: case ILOpCode.Ldlen:
return new LdLen(Pop()); return new LdLen(Pop());
case ILOpCode.Ldobj: case ILOpCode.Ldobj:
return new LdObj(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new LdObj(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Ldsfld: case ILOpCode.Ldsfld:
return new LdsFld((FieldReference)ReadAndDecodeMetadataToken()); return new LdsFld(ReadAndDecodeFieldReference());
case ILOpCode.Ldsflda: case ILOpCode.Ldsflda:
return new LdsFlda((FieldReference)ReadAndDecodeMetadataToken()); return new LdsFlda(ReadAndDecodeFieldReference());
case ILOpCode.Stsfld: case ILOpCode.Stsfld:
return new Void(new StsFld(Pop(), (FieldReference)ReadAndDecodeMetadataToken())); return new Void(new StsFld(Pop(), ReadAndDecodeFieldReference()));
case ILOpCode.Ldtoken: case ILOpCode.Ldtoken:
return new LdToken((MemberReference)ReadAndDecodeMetadataToken()); return new LdToken((MemberReference)ReadAndDecodeMetadataToken());
case ILOpCode.Ldvirtftn: case ILOpCode.Ldvirtftn:
return new LdVirtFtn(Pop(), (MethodReference)ReadAndDecodeMetadataToken()); return new LdVirtFtn(Pop(), ReadAndDecodeMethodReference());
case ILOpCode.Mkrefany: case ILOpCode.Mkrefany:
throw new NotImplementedException(); throw new NotImplementedException();
case ILOpCode.Newarr: case ILOpCode.Newarr:
@ -587,7 +646,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Rethrow: case ILOpCode.Rethrow:
return new Rethrow(); return new Rethrow();
case ILOpCode.Sizeof: case ILOpCode.Sizeof:
return new SizeOf((TypeReference)ReadAndDecodeMetadataToken()); return new SizeOf(ReadAndDecodeTypeReference());
case ILOpCode.Stelem: case ILOpCode.Stelem:
case ILOpCode.Stelem_I1: case ILOpCode.Stelem_I1:
case ILOpCode.Stelem_I2: case ILOpCode.Stelem_I2:
@ -599,13 +658,13 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stelem_Ref: case ILOpCode.Stelem_Ref:
throw new NotImplementedException(); throw new NotImplementedException();
case ILOpCode.Stobj: case ILOpCode.Stobj:
return new Void(new StObj(value: Pop(), target: Pop(), type: (TypeReference)ReadAndDecodeMetadataToken())); return new Void(new StObj(value: Pop(), target: Pop(), type: ReadAndDecodeTypeReference()));
case ILOpCode.Throw: case ILOpCode.Throw:
return new Throw(Pop()); return new Throw(Pop());
case ILOpCode.Unbox: case ILOpCode.Unbox:
return new Unbox(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new Unbox(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Unbox_Any: case ILOpCode.Unbox_Any:
return new UnboxAny(Pop(), (TypeReference)ReadAndDecodeMetadataToken()); return new UnboxAny(Pop(), ReadAndDecodeTypeReference());
default: default:
throw new NotImplementedException(ilOpCode.ToString()); throw new NotImplementedException(ilOpCode.ToString());
} }
@ -668,7 +727,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction DecodeConstrainedCall() private ILInstruction DecodeConstrainedCall()
{ {
var typeRef = ReadAndDecodeMetadataToken() as TypeReference; var typeRef = ReadAndDecodeTypeReference();
var inst = DecodeInstruction(); var inst = DecodeInstruction();
var call = inst as CallInstruction; var call = inst as CallInstruction;
if (call != null) if (call != null)
@ -721,8 +780,8 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction DecodeCall(OpCode opCode) ILInstruction DecodeCall(OpCode opCode)
{ {
var method = (MethodReference)ReadAndDecodeMetadataToken(); var method = ReadAndDecodeMethodReference();
var arguments = new ILInstruction[CallInstruction.GetPopCount(opCode, method)]; var arguments = new ILInstruction[GetPopCount(opCode, method)];
for (int i = arguments.Length - 1; i >= 0; i--) { for (int i = arguments.Length - 1; i >= 0; i--) {
arguments[i] = Pop(); arguments[i] = Pop();
} }
@ -731,6 +790,22 @@ namespace ICSharpCode.Decompiler.IL
return call; return call;
} }
static int GetPopCount(OpCode callCode, MethodReference methodReference)
{
int popCount = methodReference.Parameters.Count;
if (callCode != OpCode.NewObj && methodReference.HasThis)
popCount++;
return popCount;
}
static int GetPopCount(OpCode callCode, IMethod method)
{
int popCount = method.Parameters.Count;
if (callCode != OpCode.NewObj && !method.IsStatic)
popCount++;
return popCount;
}
ILInstruction Comparison(OpCode opCode_I, OpCode opCode_F) ILInstruction Comparison(OpCode opCode_I, OpCode opCode_F)
{ {
var right = Pop(); var right = Pop();

5
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -38,11 +38,6 @@ namespace ICSharpCode.Decompiler.IL
return ImmutableArray.Create(result); return ImmutableArray.Create(result);
}*/ }*/
public static int GetPopAmount(this MethodReference methodRef)
{
return methodRef.Parameters.Count + (methodRef.HasThis ? 1 : 0);
}
public static StackType GetStackType(this TypeReference typeRef) public static StackType GetStackType(this TypeReference typeRef)
{ {
typeRef = typeRef.SkipModifiers(); typeRef = typeRef.SkipModifiers();

36
ICSharpCode.Decompiler/IL/ILVariable.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 ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using System; using System;
@ -44,10 +45,10 @@ namespace ICSharpCode.Decompiler.IL
public class ILVariable public class ILVariable
{ {
public readonly VariableKind Kind; public readonly VariableKind Kind;
public readonly TypeReference Type; public readonly IType Type;
public readonly int Index; public readonly int Index;
public string Name; public string Name { get; set; }
/// <summary> /// <summary>
/// Number of ldloc instructions referencing this variable. /// Number of ldloc instructions referencing this variable.
@ -64,9 +65,7 @@ namespace ICSharpCode.Decompiler.IL
/// </summary> /// </summary>
public int AddressCount; public int AddressCount;
readonly object CecilObject; public ILVariable(VariableKind kind, IType type, int index)
public ILVariable(VariableKind kind, TypeReference type, int index)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException("type"); throw new ArgumentNullException("type");
@ -75,29 +74,6 @@ namespace ICSharpCode.Decompiler.IL
this.Index = index; this.Index = index;
} }
public ILVariable(VariableDefinition v)
: this(VariableKind.Local, v.VariableType, v.Index)
{
this.CecilObject = v;
if (string.IsNullOrEmpty(v.Name))
this.Name = "V_" + v.Index;
else
this.Name = v.Name;
}
public ILVariable(ParameterDefinition p)
: this(p.Index == -1 ? VariableKind.This : VariableKind.Parameter, p.ParameterType, p.Index)
{
this.CecilObject = p;
this.StoreCount = 1; // count the initial store when the method is called with an argument
if (this.Kind == VariableKind.This)
this.Name = "this";
else if (string.IsNullOrEmpty(p.Name))
this.Name = "P_" + this.Index;
else
this.Name = p.Name;
}
public override string ToString() public override string ToString()
{ {
return Name; return Name;
@ -105,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL
internal void WriteDefinitionTo(ITextOutput output) internal void WriteDefinitionTo(ITextOutput output)
{ {
output.WriteDefinition(this.Name, CecilObject ?? this, isLocal: true); output.WriteDefinition(this.Name, this, isLocal: true);
output.Write(" : "); output.Write(" : ");
Type.WriteTo(output); Type.WriteTo(output);
output.Write("({0} ldloc, {1} ldloca, {2} stloc)", LoadCount, AddressCount, StoreCount); output.Write("({0} ldloc, {1} ldloca, {2} stloc)", LoadCount, AddressCount, StoreCount);
@ -113,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL
internal void WriteTo(ITextOutput output) internal void WriteTo(ITextOutput output)
{ {
output.WriteReference(this.Name, CecilObject ?? this, isLocal: true); output.WriteReference(this.Name, this, isLocal: true);
} }
} }
} }

12
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -21,6 +21,8 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
@ -40,5 +42,15 @@ namespace ICSharpCode.Decompiler.IL
{ {
output.Write(primitiveType.ToString().ToLowerInvariant()); output.Write(primitiveType.ToString().ToLowerInvariant());
} }
public static void WriteTo(this IType type, ITextOutput output, ILNameSyntax nameSyntax = ILNameSyntax.ShortTypeName)
{
output.WriteReference(type.ToString(), type);
}
public static void WriteTo(this ISymbol symbol, ITextOutput output)
{
output.WriteReference(symbol.ToString(), symbol);
}
} }
} }

136
ICSharpCode.Decompiler/IL/Instructions.cs

@ -19,7 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Mono.Cecil; using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
@ -772,7 +772,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Non-virtual method call.</summary> /// <summary>Non-virtual method call.</summary>
public sealed partial class Call : CallInstruction public sealed partial class Call : CallInstruction
{ {
public Call(MethodReference method) : base(OpCode.Call, method) public Call(IMethod method) : base(OpCode.Call, method)
{ {
} }
@ -785,7 +785,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Virtual method call.</summary> /// <summary>Virtual method call.</summary>
public sealed partial class CallVirt : CallInstruction public sealed partial class CallVirt : CallInstruction
{ {
public CallVirt(MethodReference method) : base(OpCode.CallVirt, method) public CallVirt(IMethod method) : base(OpCode.CallVirt, method)
{ {
} }
@ -1024,13 +1024,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load method pointer</summary> /// <summary>Load method pointer</summary>
public sealed partial class LdFtn : SimpleInstruction public sealed partial class LdFtn : SimpleInstruction
{ {
public LdFtn(MethodReference method) : base(OpCode.LdFtn) public LdFtn(IMethod method) : base(OpCode.LdFtn)
{ {
this.method = method; this.method = method;
} }
readonly MethodReference method; readonly IMethod method;
/// <summary>Returns the method operand.</summary> /// <summary>Returns the method operand.</summary>
public MethodReference Method { get { return method; } } public IMethod Method { get { return method; } }
public override StackType ResultType { get { return StackType.I; } } public override StackType ResultType { get { return StackType.I; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1047,13 +1047,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load method pointer</summary> /// <summary>Load method pointer</summary>
public sealed partial class LdVirtFtn : UnaryInstruction public sealed partial class LdVirtFtn : UnaryInstruction
{ {
public LdVirtFtn(ILInstruction argument, MethodReference method) : base(OpCode.LdVirtFtn, argument) public LdVirtFtn(ILInstruction argument, IMethod method) : base(OpCode.LdVirtFtn, argument)
{ {
this.method = method; this.method = method;
} }
readonly MethodReference method; readonly IMethod method;
/// <summary>Returns the method operand.</summary> /// <summary>Returns the method operand.</summary>
public MethodReference Method { get { return method; } } public IMethod Method { get { return method; } }
public override StackType ResultType { get { return StackType.I; } } public override StackType ResultType { get { return StackType.I; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1077,13 +1077,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Loads runtime representation of metadata token</summary> /// <summary>Loads runtime representation of metadata token</summary>
public sealed partial class LdToken : SimpleInstruction public sealed partial class LdToken : SimpleInstruction
{ {
public LdToken(MemberReference member) : base(OpCode.LdToken) public LdToken(Mono.Cecil.MemberReference member) : base(OpCode.LdToken)
{ {
this.member = member; this.member = member;
} }
readonly MemberReference member; readonly Mono.Cecil.MemberReference member;
/// <summary>Returns the token operand.</summary> /// <summary>Returns the token operand.</summary>
public MemberReference Member { get { return member; } } public Mono.Cecil.MemberReference Member { get { return member; } }
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1153,7 +1153,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load instance field</summary> /// <summary>Load instance field</summary>
public sealed partial class LdFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class LdFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public LdFld(ILInstruction target, FieldReference field) : base(OpCode.LdFld) public LdFld(ILInstruction target, IField field) : base(OpCode.LdFld)
{ {
this.Target = target; this.Target = target;
this.field = field; this.field = field;
@ -1184,10 +1184,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; } public byte UnalignedPrefix { get; set; }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } } public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
@ -1214,7 +1214,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load address of instance field</summary> /// <summary>Load address of instance field</summary>
public sealed partial class LdFlda : ILInstruction public sealed partial class LdFlda : ILInstruction
{ {
public LdFlda(ILInstruction target, FieldReference field) : base(OpCode.LdFlda) public LdFlda(ILInstruction target, IField field) : base(OpCode.LdFlda)
{ {
this.Target = target; this.Target = target;
this.field = field; this.field = field;
@ -1241,9 +1241,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished); this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this; return this;
} }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1267,7 +1267,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Store value to instance field</summary> /// <summary>Store value to instance field</summary>
public sealed partial class StFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class StFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public StFld(ILInstruction target, ILInstruction value, FieldReference field) : base(OpCode.StFld) public StFld(ILInstruction target, ILInstruction value, IField field) : base(OpCode.StFld)
{ {
this.Target = target; this.Target = target;
this.Value = value; this.Value = value;
@ -1311,10 +1311,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; } public byte UnalignedPrefix { get; set; }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } } public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
@ -1343,7 +1343,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load static field</summary> /// <summary>Load static field</summary>
public sealed partial class LdsFld : SimpleInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class LdsFld : SimpleInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public LdsFld(FieldReference field) : base(OpCode.LdsFld) public LdsFld(IField field) : base(OpCode.LdsFld)
{ {
this.field = field; this.field = field;
} }
@ -1351,10 +1351,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; } public byte UnalignedPrefix { get; set; }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } } public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
return InstructionFlags.SideEffect; return InstructionFlags.SideEffect;
@ -1378,14 +1378,14 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load static field address</summary> /// <summary>Load static field address</summary>
public sealed partial class LdsFlda : SimpleInstruction public sealed partial class LdsFlda : SimpleInstruction
{ {
public LdsFlda(FieldReference field) : base(OpCode.LdsFlda) public LdsFlda(IField field) : base(OpCode.LdsFlda)
{ {
this.field = field; this.field = field;
} }
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
output.Write(OpCode); output.Write(OpCode);
@ -1401,7 +1401,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Store value to static field</summary> /// <summary>Store value to static field</summary>
public sealed partial class StsFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class StsFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public StsFld(ILInstruction value, FieldReference field) : base(OpCode.StsFld) public StsFld(ILInstruction value, IField field) : base(OpCode.StsFld)
{ {
this.Value = value; this.Value = value;
this.field = field; this.field = field;
@ -1432,10 +1432,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; } public byte UnalignedPrefix { get; set; }
readonly FieldReference field; readonly IField field;
/// <summary>Returns the field operand.</summary> /// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } } public IField Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } } public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
return value.Flags | InstructionFlags.SideEffect; return value.Flags | InstructionFlags.SideEffect;
@ -1462,13 +1462,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Casts an object to a class.</summary> /// <summary>Casts an object to a class.</summary>
public sealed partial class CastClass : UnaryInstruction public sealed partial class CastClass : UnaryInstruction
{ {
public CastClass(ILInstruction argument, TypeReference type) : base(OpCode.CastClass, argument) public CastClass(ILInstruction argument, IType type) : base(OpCode.CastClass, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1492,13 +1492,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Test if object is instance of class or interface.</summary> /// <summary>Test if object is instance of class or interface.</summary>
public sealed partial class IsInst : UnaryInstruction public sealed partial class IsInst : UnaryInstruction
{ {
public IsInst(ILInstruction argument, TypeReference type) : base(OpCode.IsInst, argument) public IsInst(ILInstruction argument, IType type) : base(OpCode.IsInst, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1518,7 +1518,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Indirect load (ref/pointer dereference).</summary> /// <summary>Indirect load (ref/pointer dereference).</summary>
public sealed partial class LdObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class LdObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public LdObj(ILInstruction target, TypeReference type) : base(OpCode.LdObj) public LdObj(ILInstruction target, IType type) : base(OpCode.LdObj)
{ {
this.Target = target; this.Target = target;
this.type = type; this.type = type;
@ -1545,9 +1545,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished); this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this; return this;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
/// <summary>Gets/Sets whether the memory access is volatile.</summary> /// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -1579,7 +1579,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Indirect store (store to ref/pointer).</summary> /// <summary>Indirect store (store to ref/pointer).</summary>
public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
public StObj(ILInstruction target, ILInstruction value, TypeReference type) : base(OpCode.StObj) public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj)
{ {
this.Target = target; this.Target = target;
this.Value = value; this.Value = value;
@ -1619,9 +1619,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished); this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this; return this;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
/// <summary>Gets/Sets whether the memory access is volatile.</summary> /// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; } public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> /// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -1655,13 +1655,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Boxes a value.</summary> /// <summary>Boxes a value.</summary>
public sealed partial class Box : UnaryInstruction public sealed partial class Box : UnaryInstruction
{ {
public Box(ILInstruction argument, TypeReference type) : base(OpCode.Box, argument) public Box(ILInstruction argument, IType type) : base(OpCode.Box, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1685,13 +1685,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Compute address inside box.</summary> /// <summary>Compute address inside box.</summary>
public sealed partial class Unbox : UnaryInstruction public sealed partial class Unbox : UnaryInstruction
{ {
public Unbox(ILInstruction argument, TypeReference type) : base(OpCode.Unbox, argument) public Unbox(ILInstruction argument, IType type) : base(OpCode.Unbox, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1715,13 +1715,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Unbox a value.</summary> /// <summary>Unbox a value.</summary>
public sealed partial class UnboxAny : UnaryInstruction public sealed partial class UnboxAny : UnaryInstruction
{ {
public UnboxAny(ILInstruction argument, TypeReference type) : base(OpCode.UnboxAny, argument) public UnboxAny(ILInstruction argument, IType type) : base(OpCode.UnboxAny, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
@ -1745,7 +1745,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Creates an object instance and calls the constructor.</summary> /// <summary>Creates an object instance and calls the constructor.</summary>
public sealed partial class NewObj : CallInstruction public sealed partial class NewObj : CallInstruction
{ {
public NewObj(MethodReference method) : base(OpCode.NewObj, method) public NewObj(IMethod method) : base(OpCode.NewObj, method)
{ {
} }
public override StackType ResultType { get { return StackType.O; } } public override StackType ResultType { get { return StackType.O; } }
@ -1758,13 +1758,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Initializes the value at an address.</summary> /// <summary>Initializes the value at an address.</summary>
public sealed partial class InitObj : UnaryInstruction public sealed partial class InitObj : UnaryInstruction
{ {
public InitObj(ILInstruction argument, TypeReference type) : base(OpCode.InitObj, argument) public InitObj(ILInstruction argument, IType type) : base(OpCode.InitObj, argument)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.Void; } } public override StackType ResultType { get { return StackType.Void; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1784,13 +1784,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the default value for a type.</summary> /// <summary>Returns the default value for a type.</summary>
public sealed partial class DefaultValue : SimpleInstruction public sealed partial class DefaultValue : SimpleInstruction
{ {
public DefaultValue(TypeReference type) : base(OpCode.DefaultValue) public DefaultValue(IType type) : base(OpCode.DefaultValue)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return type.GetStackType(); } } public override StackType ResultType { get { return type.GetStackType(); } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1841,13 +1841,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Gets the size of a type in bytes.</summary> /// <summary>Gets the size of a type in bytes.</summary>
public sealed partial class SizeOf : SimpleInstruction public sealed partial class SizeOf : SimpleInstruction
{ {
public SizeOf(TypeReference type) : base(OpCode.SizeOf) public SizeOf(IType type) : base(OpCode.SizeOf)
{ {
this.type = type; this.type = type;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.I4; } } public override StackType ResultType { get { return StackType.I4; } }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
@ -1911,7 +1911,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load address of array element.</summary> /// <summary>Load address of array element.</summary>
public sealed partial class LdElema : ILInstruction public sealed partial class LdElema : ILInstruction
{ {
public LdElema(ILInstruction array, ILInstruction index, TypeReference type) : base(OpCode.LdElema) public LdElema(ILInstruction array, ILInstruction index, IType type) : base(OpCode.LdElema)
{ {
this.Array = array; this.Array = array;
this.Index = index; this.Index = index;
@ -1951,9 +1951,9 @@ namespace ICSharpCode.Decompiler.IL
this.Array = this.array.Inline(flagsBefore, instructionStack, out finished); this.Array = this.array.Inline(flagsBefore, instructionStack, out finished);
return this; return this;
} }
readonly TypeReference type; readonly IType type;
/// <summary>Returns the type operand.</summary> /// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } } public IType Type { get { return type; } }
public override StackType ResultType { get { return StackType.Ref; } } public override StackType ResultType { get { return StackType.Ref; } }
/// <summary>Gets whether the 'readonly' prefix was applied to this instruction.</summary> /// <summary>Gets whether the 'readonly' prefix was applied to this instruction.</summary>
public bool IsReadOnly { get; set; } public bool IsReadOnly { get; set; }

36
ICSharpCode.Decompiler/IL/Instructions.tt

@ -133,22 +133,22 @@
new OpCode("ldfld", "Load instance field", new OpCode("ldfld", "Load instance field",
CustomClassName("LdFld"), CustomArguments("target"), MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, CustomClassName("LdFld"), CustomArguments("target"), MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow,
HasFieldOperand, ResultType("field.FieldType.GetStackType()")), HasFieldOperand, ResultType("field.Type.GetStackType()")),
new OpCode("ldflda", "Load address of instance field", new OpCode("ldflda", "Load address of instance field",
CustomClassName("LdFlda"), CustomArguments("target"), MayThrow, HasFieldOperand, ResultType("Ref")), CustomClassName("LdFlda"), CustomArguments("target"), MayThrow, HasFieldOperand, ResultType("Ref")),
new OpCode("stfld", "Store value to instance field", new OpCode("stfld", "Store value to instance field",
CustomClassName("StFld"), CustomArguments("target", "value"), CustomClassName("StFld"), CustomArguments("target", "value"),
MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, HasFieldOperand, MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, MayThrow, HasFieldOperand,
ResultType("field.FieldType.GetStackType()")), ResultType("field.Type.GetStackType()")),
new OpCode("ldsfld", "Load static field", new OpCode("ldsfld", "Load static field",
CustomClassName("LdsFld"), NoArguments, MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, CustomClassName("LdsFld"), NoArguments, MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix,
HasFieldOperand, ResultType("field.FieldType.GetStackType()")), HasFieldOperand, ResultType("field.Type.GetStackType()")),
new OpCode("ldsflda", "Load static field address", new OpCode("ldsflda", "Load static field address",
CustomClassName("LdsFlda"), NoArguments, ResultType("Ref"), HasFieldOperand), CustomClassName("LdsFlda"), NoArguments, ResultType("Ref"), HasFieldOperand),
new OpCode("stsfld", "Store value to static field", new OpCode("stsfld", "Store value to static field",
CustomClassName("StsFld"), CustomArguments("value"), CustomClassName("StsFld"), CustomArguments("value"),
MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, HasFieldOperand, MemoryAccess, SupportsVolatilePrefix, SupportsUnalignedPrefix, HasFieldOperand,
ResultType("field.FieldType.GetStackType()")), ResultType("field.Type.GetStackType()")),
new OpCode("castclass", "Casts an object to a class.", new OpCode("castclass", "Casts an object to a class.",
CustomClassName("CastClass"), Unary, HasTypeOperand, MayThrow, ResultType("type.GetStackType()")), CustomClassName("CastClass"), Unary, HasTypeOperand, MayThrow, ResultType("type.GetStackType()")),
@ -190,7 +190,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using Mono.Cecil; using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
@ -631,7 +631,7 @@ namespace ICSharpCode.Decompiler.IL
// Call trait: the instruction performs a method call // Call trait: the instruction performs a method call
static Action<OpCode> Call = opCode => { static Action<OpCode> Call = opCode => {
opCode.BaseClass = "CallInstruction"; opCode.BaseClass = "CallInstruction";
opCode.ConstructorParameters.Add("MethodReference method"); opCode.ConstructorParameters.Add("IMethod method");
opCode.BaseConstructorArguments.Add("method"); opCode.BaseConstructorArguments.Add("method");
}; };
@ -649,44 +649,44 @@ namespace ICSharpCode.Decompiler.IL
}; };
static Action<OpCode> HasFieldOperand = opCode => { static Action<OpCode> HasFieldOperand = opCode => {
opCode.ConstructorParameters.Add("FieldReference field"); opCode.ConstructorParameters.Add("IField field");
opCode.Members.Add("readonly FieldReference field;"); opCode.Members.Add("readonly IField field;");
opCode.ConstructorBody.Add("this.field = field;"); opCode.ConstructorBody.Add("this.field = field;");
opCode.Members.Add("/// <summary>Returns the field operand.</summary>" + Environment.NewLine opCode.Members.Add("/// <summary>Returns the field operand.</summary>" + Environment.NewLine
+ "public FieldReference Field { get { return field; } }"); + "public IField Field { get { return field; } }");
opCode.GenerateWriteTo = true; opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, field);"); opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, field);");
}; };
static Action<OpCode> HasTypeOperand = opCode => { static Action<OpCode> HasTypeOperand = opCode => {
opCode.ConstructorParameters.Add("TypeReference type"); opCode.ConstructorParameters.Add("IType type");
opCode.Members.Add("readonly TypeReference type;"); opCode.Members.Add("readonly IType type;");
opCode.ConstructorBody.Add("this.type = type;"); opCode.ConstructorBody.Add("this.type = type;");
opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine
+ "public TypeReference Type { get { return type; } }"); + "public IType Type { get { return type; } }");
opCode.GenerateWriteTo = true; opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, type);"); opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, type);");
}; };
static Action<OpCode> HasMethodOperand = opCode => { static Action<OpCode> HasMethodOperand = opCode => {
opCode.ConstructorParameters.Add("MethodReference method"); opCode.ConstructorParameters.Add("IMethod method");
opCode.Members.Add("readonly MethodReference method;"); opCode.Members.Add("readonly IMethod method;");
opCode.ConstructorBody.Add("this.method = method;"); opCode.ConstructorBody.Add("this.method = method;");
opCode.Members.Add("/// <summary>Returns the method operand.</summary>" + Environment.NewLine opCode.Members.Add("/// <summary>Returns the method operand.</summary>" + Environment.NewLine
+ "public MethodReference Method { get { return method; } }"); + "public IMethod Method { get { return method; } }");
opCode.GenerateWriteTo = true; opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, method);"); opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, method);");
}; };
static Action<OpCode> HasTokenOperand = opCode => { static Action<OpCode> HasTokenOperand = opCode => {
opCode.ConstructorParameters.Add("MemberReference member"); opCode.ConstructorParameters.Add("Mono.Cecil.MemberReference member");
opCode.Members.Add("readonly MemberReference member;"); opCode.Members.Add("readonly Mono.Cecil.MemberReference member;");
opCode.ConstructorBody.Add("this.member = member;"); opCode.ConstructorBody.Add("this.member = member;");
opCode.Members.Add("/// <summary>Returns the token operand.</summary>" + Environment.NewLine opCode.Members.Add("/// <summary>Returns the token operand.</summary>" + Environment.NewLine
+ "public MemberReference Member { get { return member; } }"); + "public Mono.Cecil.MemberReference Member { get { return member; } }");
opCode.GenerateWriteTo = true; opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');"); opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, member);"); opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, member);");

21
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -22,14 +22,14 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Mono.Cecil; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{ {
public abstract class CallInstruction : ILInstruction public abstract class CallInstruction : ILInstruction
{ {
public static CallInstruction Create(OpCode opCode, MethodReference method) public static CallInstruction Create(OpCode opCode, IMethod method)
{ {
switch (opCode) { switch (opCode) {
case OpCode.Call: case OpCode.Call:
@ -44,22 +44,15 @@ namespace ICSharpCode.Decompiler.IL
} }
public readonly InstructionCollection<ILInstruction> Arguments; public readonly InstructionCollection<ILInstruction> Arguments;
public readonly MethodReference Method; public readonly IMethod Method;
protected CallInstruction(OpCode opCode, MethodReference methodReference) : base(opCode) protected CallInstruction(OpCode opCode, IMethod method) : base(opCode)
{ {
this.Method = methodReference; Debug.Assert(method != null);
this.Method = method;
this.Arguments = new InstructionCollection<ILInstruction>(this); this.Arguments = new InstructionCollection<ILInstruction>(this);
} }
public static int GetPopCount(OpCode callCode, MethodReference methodReference)
{
int popCount = methodReference.Parameters.Count;
if (callCode != OpCode.NewObj && methodReference.HasThis)
popCount++;
return popCount;
}
public override StackType ResultType { public override StackType ResultType {
get { get {
if (OpCode == OpCode.NewObj) if (OpCode == OpCode.NewObj)
@ -97,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets/Sets the type specified in the 'constrained.' prefix. /// Gets/Sets the type specified in the 'constrained.' prefix.
/// Returns null if no 'constrained.' prefix exists for this call. /// Returns null if no 'constrained.' prefix exists for this call.
/// </summary> /// </summary>
public TypeReference ConstrainedTo; public IType ConstrainedTo;
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {

8
ICSharpCode.Decompiler/ReferenceResolvingException.cs

@ -30,14 +30,14 @@ namespace ICSharpCode.Decompiler
public class ReferenceResolvingException : Exception public class ReferenceResolvingException : Exception
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class /// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary> /// </summary>
public ReferenceResolvingException() public ReferenceResolvingException()
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class /// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary> /// </summary>
/// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param> /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
public ReferenceResolvingException(string message) public ReferenceResolvingException(string message)
@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class /// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary> /// </summary>
/// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param> /// <param name="message">A <see cref="T:System.String"/> that describes the error. The content of message is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture.</param>
/// <param name="inner">The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param> /// <param name="inner">The exception that is the cause of the current exception. If the innerException parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param>
@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class /// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary> /// </summary>
/// <param name="info">The object that holds the serialized object data.</param> /// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param> /// <param name="context">The contextual information about the source or destination.</param>

3
ICSharpCode.Decompiler/Tests/Helpers/Tester.cs

@ -63,7 +63,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
public static string DecompileCSharp(string assemblyFileName) public static string DecompileCSharp(string assemblyFileName)
{ {
CSharpDecompiler decompiler = new CSharpDecompiler(AssemblyDefinition.ReadAssembly(assemblyFileName).MainModule); var typeSystem = new DecompilerTypeSystem(ModuleDefinition.ReadModule(assemblyFileName));
CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem);
var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile();
new Helpers.RemoveCompilerAttribute().Run(syntaxTree); new Helpers.RemoveCompilerAttribute().Run(syntaxTree);

3
ILSpy.BamlDecompiler/Tests/TestRunner.cs

@ -16,6 +16,7 @@ using Ricciolo.StylesExplorer.MarkupReflection;
namespace ILSpy.BamlDecompiler.Tests namespace ILSpy.BamlDecompiler.Tests
{ {
/*
[TestFixture] [TestFixture]
public class TestRunner public class TestRunner
{ {
@ -135,5 +136,5 @@ namespace ILSpy.BamlDecompiler.Tests
return null; return null;
} }
#endregion #endregion
} }*/
} }

6
ILSpy/Languages/ILAstLanguage.cs

@ -128,7 +128,8 @@ namespace ICSharpCode.ILSpy
base.DecompileMethod(method, output, options); base.DecompileMethod(method, output, options);
if (!method.HasBody) if (!method.HasBody)
return; return;
ILReader reader = new ILReader(); var typeSystem = new DecompilerTypeSystem(method.Module);
ILReader reader = new ILReader(typeSystem);
reader.WriteTypedIL(method.Body, output, options.CancellationToken); reader.WriteTypedIL(method.Body, output, options.CancellationToken);
} }
} }
@ -147,7 +148,8 @@ namespace ICSharpCode.ILSpy
base.DecompileMethod(method, output, options); base.DecompileMethod(method, output, options);
if (!method.HasBody) if (!method.HasBody)
return; return;
ILReader reader = new ILReader(); var typeSystem = new DecompilerTypeSystem(method.Module);
ILReader reader = new ILReader(typeSystem);
ILInstruction il = reader.ReadIL(method.Body, options.CancellationToken); ILInstruction il = reader.ReadIL(method.Body, options.CancellationToken);
if (transformer != null) if (transformer != null)
il = il.AcceptVisitor(transformer); il = il.AcceptVisitor(transformer);

Loading…
Cancel
Save