Browse Source

Use NRefactory.TypeSystem for ILAst.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
2f83334c2e
  1. 89
      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. 12
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  13. 181
      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

89
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -35,27 +35,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -35,27 +35,9 @@ namespace ICSharpCode.Decompiler.CSharp
{
public class CSharpDecompiler
{
CecilLoader cecilLoader = new CecilLoader { IncludeInternalMembers = true, LazyLoad = true };
Dictionary<IUnresolvedEntity, MemberReference> entityDict = new Dictionary<IUnresolvedEntity, MemberReference>();
NRefactoryCecilMapper cecilMapper;
ICompilation compilation;
readonly DecompilerTypeSystem typeSystem;
TypeSystemAstBuilder typeSystemAstBuilder;
List<IAstTransform> astTransforms = new List<IAstTransform> {
//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(),
};
List<IAstTransform> astTransforms;
public CancellationToken CancellationToken { get; set; }
@ -65,52 +47,51 @@ namespace ICSharpCode.Decompiler.CSharp @@ -65,52 +47,51 @@ namespace ICSharpCode.Decompiler.CSharp
public IList<IAstTransform> AstTransforms {
get { return astTransforms; }
}
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);
var referencedAssemblies = new List<IUnresolvedAssembly>();
foreach (var asmRef in module.AssemblyReferences) {
var asm = module.AssemblyResolver.Resolve(asmRef);
if (asm != null)
referencedAssemblies.Add(cecilLoader.LoadAssembly(asm));
}
compilation = new SimpleCompilation(mainAssembly, referencedAssemblies);
cecilMapper = new NRefactoryCecilMapper(compilation, module, GetMemberReference);
public CSharpDecompiler(DecompilerTypeSystem typeSystem)
{
if (typeSystem == null)
throw new ArgumentNullException("typeSystem");
this.typeSystem = typeSystem;
astTransforms = new List<IAstTransform> {
//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(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.AlwaysUseShortTypeNames = 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)
{
var context = new TransformContext(compilation, cecilMapper);
foreach (var transform in astTransforms)
transform.Run(rootNode, context);
transform.Run(rootNode);
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
}
public SyntaxTree DecompileWholeModuleAsSingleFile()
{
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;
if (string.IsNullOrEmpty(g.Key)) {
groupNode = syntaxTree;
@ -135,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -135,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (typeDefinition == null)
throw new ArgumentNullException("typeDefinition");
ITypeDefinition typeDef = cecilMapper.GetType(typeDefinition).GetDefinition();
ITypeDefinition typeDef = typeSystem.GetType(typeDefinition).GetDefinition();
if (typeDef == null)
throw new InvalidOperationException("Could not find type definition in NR type system");
var decl = DoDecompile(typeDef);
@ -152,7 +133,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -152,7 +133,7 @@ namespace ICSharpCode.Decompiler.CSharp
return entityDecl;
}
foreach (var method in typeDef.Methods) {
var methodDef = cecilMapper.GetCecil(method) as MethodDefinition;
var methodDef = typeSystem.GetCecil(method) as MethodDefinition;
if (methodDef != null) {
var memberDecl = DoDecompile(methodDef, method);
typeDecl.Members.Add(memberDecl);
@ -165,7 +146,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -165,7 +146,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
if (methodDefinition == null)
throw new ArgumentNullException("methodDefinition");
var method = cecilMapper.GetMethod(methodDefinition);
var method = typeSystem.GetMethod(methodDefinition);
if (method == null)
throw new InvalidOperationException("Could not find method in NR type system");
var decl = DoDecompile(methodDefinition, method);
@ -177,19 +158,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -177,19 +158,19 @@ namespace ICSharpCode.Decompiler.CSharp
{
var entityDecl = typeSystemAstBuilder.ConvertEntity(method);
if (methodDefinition.HasBody) {
var ilReader = new ILReader();
var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(methodDefinition.Body, CancellationToken);
function.CheckInvariant();
function.Body = function.Body.AcceptVisitor(new TransformingVisitor());
function.CheckInvariant();
var statementBuilder = new StatementBuilder(method, cecilMapper);
var statementBuilder = new StatementBuilder(method);
var body = statementBuilder.ConvertAsBlock(function.Body);
// insert variables at start of body
Statement prevVarDecl = null;
foreach (var v in function.Variables) {
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);
body.Statements.InsertAfter(prevVarDecl, varDecl);
prevVarDecl = varDecl;

91
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -38,28 +38,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -38,28 +38,17 @@ namespace ICSharpCode.Decompiler.CSharp
class ExpressionBuilder : ILVisitor<TranslatedExpression>
{
internal readonly ICompilation compilation;
internal readonly NRefactoryCecilMapper cecilMapper;
internal readonly CSharpResolver resolver;
internal readonly TypeSystemAstBuilder astBuilder;
public ExpressionBuilder(ICompilation compilation, NRefactoryCecilMapper cecilMapper)
public ExpressionBuilder(ICompilation compilation)
{
Debug.Assert(compilation != null);
Debug.Assert(cecilMapper != null);
this.compilation = compilation;
this.cecilMapper = cecilMapper;
this.resolver = new CSharpResolver(compilation);
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)
{
var astType = astBuilder.ConvertType(type);
@ -89,36 +78,34 @@ namespace ICSharpCode.Decompiler.CSharp @@ -89,36 +78,34 @@ namespace ICSharpCode.Decompiler.CSharp
else
expr = new IdentifierExpression(variable.Name);
// 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'.
// We'll strip away the 'ref' when dereferencing.
// Ensure that the IdentifierExpression itself also gets a resolve result, as that might
// get used after the 'ref' is stripped away:
var elementType = variable.Type.SkipModifiers().GetElementType();
expr.WithRR(new ResolveResult(cecilMapper.GetType(elementType)));
var elementType = ((ByReferenceType)variable.Type).ElementType;
expr.WithRR(new ResolveResult(elementType));
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)
{
var arg = Translate(inst.Argument);
var type = cecilMapper.GetType(inst.Type);
return new IsExpression(arg.Expression, ConvertType(type))
return new IsExpression(arg.Expression, ConvertType(inst.Type))
.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)
{
var arg = Translate(inst.Argument);
var type = cecilMapper.GetType(inst.Type);
return new AsExpression(arg.Expression, ConvertType(type))
return new AsExpression(arg.Expression, ConvertType(inst.Type))
.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)
@ -374,52 +361,36 @@ namespace ICSharpCode.Decompiler.CSharp @@ -374,52 +361,36 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression HandleCallInstruction(CallInstruction inst)
{
// Used for Call, CallVirt and NewObj
var method = cecilMapper.GetMethod(inst.Method);
TranslatedExpression target;
if (inst.OpCode == OpCode.NewObj) {
target = default(TranslatedExpression); // no target
} else if (inst.Method.HasThis) {
} else if (!inst.Method.IsStatic) {
var argInstruction = inst.Arguments[0];
if (inst.OpCode == OpCode.Call && argInstruction.MatchLdThis()) {
target = new BaseReferenceExpression()
.WithILInstruction(argInstruction)
.WithRR(new ThisResolveResult(cecilMapper.GetType(inst.Method.DeclaringType), causesNonVirtualInvocation: true));
.WithRR(new ThisResolveResult(inst.Method.DeclaringType, causesNonVirtualInvocation: true));
} else {
target = Translate(argInstruction);
}
} else {
var declaringType = cecilMapper.GetType(inst.Method.DeclaringType);
target = new TypeReferenceExpression(ConvertType(declaringType))
target = new TypeReferenceExpression(ConvertType(inst.Method.DeclaringType))
.WithoutILInstruction()
.WithRR(new TypeResolveResult(declaringType));
.WithRR(new TypeResolveResult(inst.Method.DeclaringType));
}
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);
ResolveResult rr;
if (method != null) {
// Translate arguments to the expected parameter types
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));
}
for (int i = firstParamIndex; i < arguments.Length; i++) {
var parameter = inst.Method.Parameters[i - firstParamIndex];
arguments[i] = arguments[i].ConvertTo(parameter.Type, this);
}
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);
if (inst.OpCode == OpCode.NewObj) {
@ -435,19 +406,18 @@ namespace ICSharpCode.Decompiler.CSharp @@ -435,19 +406,18 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitLdObj(LdObj inst)
{
var target = Translate(inst.Target);
var type = cecilMapper.GetType(inst.Type);
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'
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
return result;
} else {
// 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)
.WithILInstruction(inst)
.WithRR(new ResolveResult(type));
.WithRR(new ResolveResult(inst.Type));
}
}
@ -455,17 +425,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -455,17 +425,16 @@ namespace ICSharpCode.Decompiler.CSharp
{
var target = Translate(inst.Target);
var value = Translate(inst.Value);
var type = cecilMapper.GetType(inst.Type);
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'
result = target.UnwrapChild(((DirectionExpression)target.Expression).Expression);
} else {
// 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)
.WithoutILInstruction()
.WithRR(new ResolveResult(type));
.WithRR(new ResolveResult(inst.Type));
}
return Assignment(result, value).WithILInstruction(inst);
}
@ -479,7 +448,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -479,7 +448,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
return new CastExpression(ConvertType(inst.Type), arg.Expression)
.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)

116
ICSharpCode.Decompiler/CSharp/NRefactoryCecilMapper.cs

@ -1,116 +0,0 @@ @@ -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 @@ -32,9 +32,9 @@ namespace ICSharpCode.Decompiler.CSharp
readonly ExpressionBuilder exprBuilder;
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;
}

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

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

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

@ -30,16 +30,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -30,16 +30,25 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// <summary>
/// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer.
/// </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;
if (stmt == null)
return null;
return;
InvocationExpression invocation = stmt.Expression as InvocationExpression;
if (invocation == null)
return null;
return;
MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
if (mre != null && mre.MemberName == ".ctor") {
ConstructorInitializer ci = new ConstructorInitializer();
@ -48,7 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -48,7 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
else if (mre.Target is BaseReferenceExpression)
ci.ConstructorInitializerType = ConstructorInitializerType.Base;
else
return null;
return;
// Move arguments from invocation to initializer:
invocation.Arguments.MoveTo(ci.Arguments);
// Add the initializer: (unless it is the default 'base()')
@ -57,7 +66,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -57,7 +66,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// Remove the statement:
stmt.Remove();
}
return null;
}
static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement {
@ -73,21 +81,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -73,21 +81,19 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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
HandleInstanceFieldInitializers(typeDeclaration.Members);
// Now convert base constructor calls to initializers:
base.VisitTypeDeclaration(typeDeclaration, context);
base.VisitTypeDeclaration(typeDeclaration);
// Remove single empty constructor:
RemoveSingleEmptyConstructor(typeDeclaration);
// Handle initializers on static fields:
HandleStaticFieldInitializers(typeDeclaration.Members, context);
return null;
HandleStaticFieldInitializers(typeDeclaration.Members);
}
void HandleInstanceFieldInitializers(IEnumerable<AstNode> members)
@ -144,13 +150,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -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
var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);
if (staticCtor != null) {
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) {
while (true) {
ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
@ -174,14 +180,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -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),
// we also need to handle those:
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 @@ -25,18 +25,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
public interface IAstTransform
{
void Run(AstNode rootNode, TransformContext context);
}
public class TransformContext
{
internal readonly NRefactoryCecilMapper CecilMapper;
public readonly ICompilation Compilation;
internal TransformContext(ICompilation compilation, NRefactoryCecilMapper cecilMapper)
{
this.Compilation = compilation;
this.CecilMapper = cecilMapper;
}
void Run(AstNode rootNode);
}
}

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

@ -21,22 +21,22 @@ using ICSharpCode.NRefactory.CSharp; @@ -21,22 +21,22 @@ using ICSharpCode.NRefactory.CSharp;
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();
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;
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)) {
((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe;
@ -45,23 +45,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -45,23 +45,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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;
}
public override bool VisitComposedType(ComposedType composedType, object data)
public override bool VisitComposedType(ComposedType composedType)
{
if (composedType.PointerRank > 0)
return true;
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) {
BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) {
@ -81,9 +81,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -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;
if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) {
PointerReferenceExpression pre = new PointerReferenceExpression();
@ -97,9 +97,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -97,9 +97,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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;
}
}

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

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// Replaces method calls with the appropriate operator expressions.
/// Also simplifies "x = x op y" into "x op= y" where possible.
/// </summary>
public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>, IAstTransform
public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor, IAstTransform
{
static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression {
Target = new Choice {
@ -41,11 +41,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -41,11 +41,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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);
return null;
}
internal static void ProcessInvocationExpression(InvocationExpression invocationExpression)
@ -232,9 +231,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -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"
BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) {
@ -265,7 +264,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -265,7 +264,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
}
}
return null;
}
public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop)
@ -330,9 +328,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -330,9 +328,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
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
Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression);
if (m.Success) {
@ -345,12 +343,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -345,12 +343,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
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 @@ @@ -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 @@ @@ -64,7 +64,6 @@
<ItemGroup>
<Compile Include="CSharp\Annotations.cs" />
<Compile Include="CSharp\TranslatedExpression.cs" />
<Compile Include="CSharp\NRefactoryCecilMapper.cs" />
<Compile Include="CSharp\CSharpDecompiler.cs" />
<Compile Include="CSharp\ExpressionBuilder.cs" />
<Compile Include="CSharp\NRefactoryExtensions.cs" />
@ -75,6 +74,7 @@ @@ -75,6 +74,7 @@
<Compile Include="CSharp\Transforms\IAstTransform.cs" />
<Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" />
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="DecompilerTypeSystem.cs" />
<Compile Include="IL\Instructions.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

12
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -30,10 +30,14 @@ namespace ICSharpCode.Decompiler.IL @@ -30,10 +30,14 @@ namespace ICSharpCode.Decompiler.IL
class BlockBuilder
{
readonly Mono.Cecil.Cil.MethodBody body;
public BlockBuilder(Mono.Cecil.Cil.MethodBody body)
readonly DecompilerTypeSystem typeSystem;
public BlockBuilder(Mono.Cecil.Cil.MethodBody body, DecompilerTypeSystem typeSystem)
{
Debug.Assert(body != null);
Debug.Assert(typeSystem != null);
this.body = body;
this.typeSystem = typeSystem;
}
List<TryInstruction> tryInstructionList = new List<TryInstruction>();
@ -67,8 +71,8 @@ namespace ICSharpCode.Decompiler.IL @@ -67,8 +71,8 @@ namespace ICSharpCode.Decompiler.IL
tryCatchList.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";
handlerBlock.EntryPoint.Instructions.Add(new LdLoc(variable));

181
ICSharpCode.Decompiler/IL/ILReader.cs

@ -23,6 +23,7 @@ using System.Text; @@ -23,6 +23,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Collections.Immutable;
using System.Diagnostics;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
using Cil = Mono.Cecil.Cil;
using System.Collections;
@ -46,9 +47,18 @@ namespace ICSharpCode.Decompiler.IL @@ -46,9 +47,18 @@ namespace ICSharpCode.Decompiler.IL
return new MetadataToken(reader.ReadUInt32());
}
Cil.MethodBody body;
TypeSystem typeSystem;
readonly ICompilation compilation;
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;
Stack<StackType> stack;
ILVariable[] parameterVariables;
@ -64,11 +74,10 @@ namespace ICSharpCode.Decompiler.IL @@ -64,11 +74,10 @@ namespace ICSharpCode.Decompiler.IL
if (body == null)
throw new ArgumentNullException("body");
this.body = body;
this.typeSystem = body.Method.Module.TypeSystem;
this.reader = body.GetILReader();
this.stack = new Stack<StackType>(body.MaxStackSize);
this.parameterVariables = InitParameterVariables(body);
this.localVariables = body.Variables.Select(v => new ILVariable(v)).ToArray();
InitParameterVariables();
this.localVariables = body.Variables.SelectArray(CreateILVariable);
this.instructionBuilder = new List<ILInstruction>();
this.isBranchTarget = new BitArray(body.CodeSize);
this.branchStackDict = new Dictionary<int, ImmutableArray<StackType>>();
@ -80,23 +89,71 @@ namespace ICSharpCode.Decompiler.IL @@ -80,23 +89,71 @@ namespace ICSharpCode.Decompiler.IL
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;
if (body.Method.HasThis)
parameterVariables[paramIndex++] = new ILVariable(body.ThisParameter);
parameterVariables[paramIndex++] = CreateILVariable(body.ThisParameter);
foreach (var p in body.Method.Parameters)
parameterVariables[paramIndex++] = new ILVariable(p);
parameterVariables[paramIndex++] = CreateILVariable(p);
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)
{
Debug.Fail(message);
}
void ReadInstructions(Dictionary<int, ImmutableArray<StackType>> outputStacks, CancellationToken cancellationToken)
{
// Fill isBranchTarget and branchStackDict based on exception handlers
@ -120,6 +177,8 @@ namespace ICSharpCode.Decompiler.IL @@ -120,6 +177,8 @@ namespace ICSharpCode.Decompiler.IL
if (outputStacks != null)
outputStacks.Add(start, stack.ToImmutableArray());
ILInstruction decodedInstruction = DecodeInstruction();
if (decodedInstruction.ResultType == StackType.Unknown)
Warn("Unknown result type (might be due to invalid IL)");
decodedInstruction.CheckInvariant();
if (decodedInstruction.ResultType != StackType.Void)
stack.Push(decodedInstruction.ResultType);
@ -176,7 +235,7 @@ namespace ICSharpCode.Decompiler.IL @@ -176,7 +235,7 @@ namespace ICSharpCode.Decompiler.IL
{
Init(body);
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);
function.Variables.AddRange(parameterVariables);
function.Variables.AddRange(localVariables);
@ -416,29 +475,29 @@ namespace ICSharpCode.Decompiler.IL @@ -416,29 +475,29 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldstr:
return DecodeLdstr();
case ILOpCode.Ldftn:
return new LdFtn((MethodReference)ReadAndDecodeMetadataToken());
return new LdFtn(ReadAndDecodeMethodReference());
case ILOpCode.Ldind_I1:
return new LdObj(Pop(), typeSystem.SByte);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.SByte));
case ILOpCode.Ldind_I2:
return new LdObj(Pop(), typeSystem.Int16);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int16));
case ILOpCode.Ldind_I4:
return new LdObj(Pop(), typeSystem.Int32);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int32));
case ILOpCode.Ldind_I8:
return new LdObj(Pop(), typeSystem.Int64);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Int64));
case ILOpCode.Ldind_U1:
return new LdObj(Pop(), typeSystem.Byte);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Byte));
case ILOpCode.Ldind_U2:
return new LdObj(Pop(), typeSystem.UInt16);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.UInt16));
case ILOpCode.Ldind_U4:
return new LdObj(Pop(), typeSystem.UInt32);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.UInt32));
case ILOpCode.Ldind_R4:
return new LdObj(Pop(), typeSystem.Single);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Single));
case ILOpCode.Ldind_R8:
return new LdObj(Pop(), typeSystem.Double);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Double));
case ILOpCode.Ldind_I:
return new LdObj(Pop(), typeSystem.IntPtr);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.IntPtr));
case ILOpCode.Ldind_Ref:
return new LdObj(Pop(), typeSystem.Object);
return new LdObj(Pop(), compilation.FindType(KnownTypeCode.Object));
case ILOpCode.Ldloc:
return Ldloc(reader.ReadUInt16());
case ILOpCode.Ldloc_S:
@ -493,21 +552,21 @@ namespace ICSharpCode.Decompiler.IL @@ -493,21 +552,21 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Starg_S:
return Starg(reader.ReadByte());
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:
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:
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:
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:
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:
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:
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:
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:
return Stloc(reader.ReadUInt16());
case ILOpCode.Stloc_S:
@ -528,19 +587,19 @@ namespace ICSharpCode.Decompiler.IL @@ -528,19 +587,19 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Xor:
return BinaryNumeric(OpCode.BitXor);
case ILOpCode.Box:
return new Box(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new Box(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Castclass:
return new CastClass(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new CastClass(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Cpobj:
{
var type = (TypeReference)ReadAndDecodeMetadataToken();
var type = ReadAndDecodeTypeReference();
var ld = new LdObj(Pop(), type);
return new Void(new StObj(Pop(), ld, type));
}
case ILOpCode.Initobj:
return new InitObj(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new InitObj(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Isinst:
return new IsInst(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new IsInst(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Ldelem:
case ILOpCode.Ldelem_I1:
case ILOpCode.Ldelem_I2:
@ -555,27 +614,27 @@ namespace ICSharpCode.Decompiler.IL @@ -555,27 +614,27 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldelem_Ref:
throw new NotImplementedException();
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:
return new LdFld(Pop(), (FieldReference)ReadAndDecodeMetadataToken());
return new LdFld(Pop(), ReadAndDecodeFieldReference());
case ILOpCode.Ldflda:
return new LdFlda(Pop(), (FieldReference)ReadAndDecodeMetadataToken());
return new LdFlda(Pop(), ReadAndDecodeFieldReference());
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:
return new LdLen(Pop());
case ILOpCode.Ldobj:
return new LdObj(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new LdObj(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Ldsfld:
return new LdsFld((FieldReference)ReadAndDecodeMetadataToken());
return new LdsFld(ReadAndDecodeFieldReference());
case ILOpCode.Ldsflda:
return new LdsFlda((FieldReference)ReadAndDecodeMetadataToken());
return new LdsFlda(ReadAndDecodeFieldReference());
case ILOpCode.Stsfld:
return new Void(new StsFld(Pop(), (FieldReference)ReadAndDecodeMetadataToken()));
return new Void(new StsFld(Pop(), ReadAndDecodeFieldReference()));
case ILOpCode.Ldtoken:
return new LdToken((MemberReference)ReadAndDecodeMetadataToken());
case ILOpCode.Ldvirtftn:
return new LdVirtFtn(Pop(), (MethodReference)ReadAndDecodeMetadataToken());
return new LdVirtFtn(Pop(), ReadAndDecodeMethodReference());
case ILOpCode.Mkrefany:
throw new NotImplementedException();
case ILOpCode.Newarr:
@ -587,7 +646,7 @@ namespace ICSharpCode.Decompiler.IL @@ -587,7 +646,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Rethrow:
return new Rethrow();
case ILOpCode.Sizeof:
return new SizeOf((TypeReference)ReadAndDecodeMetadataToken());
return new SizeOf(ReadAndDecodeTypeReference());
case ILOpCode.Stelem:
case ILOpCode.Stelem_I1:
case ILOpCode.Stelem_I2:
@ -599,13 +658,13 @@ namespace ICSharpCode.Decompiler.IL @@ -599,13 +658,13 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stelem_Ref:
throw new NotImplementedException();
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:
return new Throw(Pop());
case ILOpCode.Unbox:
return new Unbox(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new Unbox(Pop(), ReadAndDecodeTypeReference());
case ILOpCode.Unbox_Any:
return new UnboxAny(Pop(), (TypeReference)ReadAndDecodeMetadataToken());
return new UnboxAny(Pop(), ReadAndDecodeTypeReference());
default:
throw new NotImplementedException(ilOpCode.ToString());
}
@ -668,7 +727,7 @@ namespace ICSharpCode.Decompiler.IL @@ -668,7 +727,7 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction DecodeConstrainedCall()
{
var typeRef = ReadAndDecodeMetadataToken() as TypeReference;
var typeRef = ReadAndDecodeTypeReference();
var inst = DecodeInstruction();
var call = inst as CallInstruction;
if (call != null)
@ -721,8 +780,8 @@ namespace ICSharpCode.Decompiler.IL @@ -721,8 +780,8 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction DecodeCall(OpCode opCode)
{
var method = (MethodReference)ReadAndDecodeMetadataToken();
var arguments = new ILInstruction[CallInstruction.GetPopCount(opCode, method)];
var method = ReadAndDecodeMethodReference();
var arguments = new ILInstruction[GetPopCount(opCode, method)];
for (int i = arguments.Length - 1; i >= 0; i--) {
arguments[i] = Pop();
}
@ -730,6 +789,22 @@ namespace ICSharpCode.Decompiler.IL @@ -730,6 +789,22 @@ namespace ICSharpCode.Decompiler.IL
call.Arguments.AddRange(arguments);
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)
{

5
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -38,11 +38,6 @@ namespace ICSharpCode.Decompiler.IL @@ -38,11 +38,6 @@ namespace ICSharpCode.Decompiler.IL
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)
{
typeRef = typeRef.SkipModifiers();

36
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
@ -44,10 +45,10 @@ namespace ICSharpCode.Decompiler.IL @@ -44,10 +45,10 @@ namespace ICSharpCode.Decompiler.IL
public class ILVariable
{
public readonly VariableKind Kind;
public readonly TypeReference Type;
public readonly IType Type;
public readonly int Index;
public string Name;
public string Name { get; set; }
/// <summary>
/// Number of ldloc instructions referencing this variable.
@ -64,9 +65,7 @@ namespace ICSharpCode.Decompiler.IL @@ -64,9 +65,7 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public int AddressCount;
readonly object CecilObject;
public ILVariable(VariableKind kind, TypeReference type, int index)
public ILVariable(VariableKind kind, IType type, int index)
{
if (type == null)
throw new ArgumentNullException("type");
@ -75,29 +74,6 @@ namespace ICSharpCode.Decompiler.IL @@ -75,29 +74,6 @@ namespace ICSharpCode.Decompiler.IL
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()
{
return Name;
@ -105,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL @@ -105,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL
internal void WriteDefinitionTo(ITextOutput output)
{
output.WriteDefinition(this.Name, CecilObject ?? this, isLocal: true);
output.WriteDefinition(this.Name, this, isLocal: true);
output.Write(" : ");
Type.WriteTo(output);
output.Write("({0} ldloc, {1} ldloca, {2} stloc)", LoadCount, AddressCount, StoreCount);
@ -113,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL @@ -113,7 +89,7 @@ namespace ICSharpCode.Decompiler.IL
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; @@ -21,6 +21,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL
{
@ -40,5 +42,15 @@ namespace ICSharpCode.Decompiler.IL @@ -40,5 +42,15 @@ namespace ICSharpCode.Decompiler.IL
{
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 @@ @@ -19,7 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Mono.Cecil;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
@ -772,7 +772,7 @@ namespace ICSharpCode.Decompiler.IL @@ -772,7 +772,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Non-virtual method call.</summary>
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 @@ -785,7 +785,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Virtual method call.</summary>
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 @@ -1024,13 +1024,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load method pointer</summary>
public sealed partial class LdFtn : SimpleInstruction
{
public LdFtn(MethodReference method) : base(OpCode.LdFtn)
public LdFtn(IMethod method) : base(OpCode.LdFtn)
{
this.method = method;
}
readonly MethodReference method;
readonly IMethod method;
/// <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 void WriteTo(ITextOutput output)
{
@ -1047,13 +1047,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1047,13 +1047,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load method pointer</summary>
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;
}
readonly MethodReference method;
readonly IMethod method;
/// <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; } }
protected override InstructionFlags ComputeFlags()
{
@ -1077,13 +1077,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1077,13 +1077,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Loads runtime representation of metadata token</summary>
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;
}
readonly MemberReference member;
readonly Mono.Cecil.MemberReference member;
/// <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 void WriteTo(ITextOutput output)
{
@ -1153,7 +1153,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1153,7 +1153,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load instance field</summary>
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.field = field;
@ -1184,10 +1184,10 @@ namespace ICSharpCode.Decompiler.IL @@ -1184,10 +1184,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; }
readonly FieldReference field;
readonly IField field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
public IField Field { get { return field; } }
public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
@ -1214,7 +1214,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1214,7 +1214,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load address of instance field</summary>
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.field = field;
@ -1241,9 +1241,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1241,9 +1241,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this;
}
readonly FieldReference field;
readonly IField field;
/// <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; } }
protected override InstructionFlags ComputeFlags()
{
@ -1267,7 +1267,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1267,7 +1267,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Store value to instance field</summary>
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.Value = value;
@ -1311,10 +1311,10 @@ namespace ICSharpCode.Decompiler.IL @@ -1311,10 +1311,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; }
readonly FieldReference field;
readonly IField field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
public IField Field { get { return field; } }
public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
@ -1343,7 +1343,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1343,7 +1343,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load static field</summary>
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;
}
@ -1351,10 +1351,10 @@ namespace ICSharpCode.Decompiler.IL @@ -1351,10 +1351,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; }
readonly FieldReference field;
readonly IField field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
public IField Field { get { return field; } }
public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.SideEffect;
@ -1378,14 +1378,14 @@ namespace ICSharpCode.Decompiler.IL @@ -1378,14 +1378,14 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load static field address</summary>
public sealed partial class LdsFlda : SimpleInstruction
{
public LdsFlda(FieldReference field) : base(OpCode.LdsFlda)
public LdsFlda(IField field) : base(OpCode.LdsFlda)
{
this.field = field;
}
public override StackType ResultType { get { return StackType.Ref; } }
readonly FieldReference field;
readonly IField field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public IField Field { get { return field; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
@ -1401,7 +1401,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1401,7 +1401,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Store value to static field</summary>
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.field = field;
@ -1432,10 +1432,10 @@ namespace ICSharpCode.Decompiler.IL @@ -1432,10 +1432,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; }
readonly FieldReference field;
readonly IField field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
public IField Field { get { return field; } }
public override StackType ResultType { get { return field.Type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return value.Flags | InstructionFlags.SideEffect;
@ -1462,13 +1462,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1462,13 +1462,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Casts an object to a class.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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(); } }
protected override InstructionFlags ComputeFlags()
{
@ -1492,13 +1492,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1492,13 +1492,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Test if object is instance of class or interface.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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 void WriteTo(ITextOutput output)
{
@ -1518,7 +1518,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1518,7 +1518,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Indirect load (ref/pointer dereference).</summary>
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.type = type;
@ -1545,9 +1545,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1545,9 +1545,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this;
}
readonly TypeReference type;
readonly IType type;
/// <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>
public bool IsVolatile { get; set; }
/// <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 @@ -1579,7 +1579,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Indirect store (store to ref/pointer).</summary>
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.Value = value;
@ -1619,9 +1619,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1619,9 +1619,9 @@ namespace ICSharpCode.Decompiler.IL
this.Target = this.target.Inline(flagsBefore, instructionStack, out finished);
return this;
}
readonly TypeReference type;
readonly IType type;
/// <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>
public bool IsVolatile { get; set; }
/// <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 @@ -1655,13 +1655,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Boxes a value.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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; } }
protected override InstructionFlags ComputeFlags()
{
@ -1685,13 +1685,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1685,13 +1685,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Compute address inside box.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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; } }
protected override InstructionFlags ComputeFlags()
{
@ -1715,13 +1715,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1715,13 +1715,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Unbox a value.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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(); } }
protected override InstructionFlags ComputeFlags()
{
@ -1745,7 +1745,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1745,7 +1745,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Creates an object instance and calls the constructor.</summary>
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; } }
@ -1758,13 +1758,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1758,13 +1758,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Initializes the value at an address.</summary>
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;
}
readonly TypeReference type;
readonly IType type;
/// <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 void WriteTo(ITextOutput output)
{
@ -1784,13 +1784,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1784,13 +1784,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the default value for a type.</summary>
public sealed partial class DefaultValue : SimpleInstruction
{
public DefaultValue(TypeReference type) : base(OpCode.DefaultValue)
public DefaultValue(IType type) : base(OpCode.DefaultValue)
{
this.type = type;
}
readonly TypeReference type;
readonly IType type;
/// <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 void WriteTo(ITextOutput output)
{
@ -1841,13 +1841,13 @@ namespace ICSharpCode.Decompiler.IL @@ -1841,13 +1841,13 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Gets the size of a type in bytes.</summary>
public sealed partial class SizeOf : SimpleInstruction
{
public SizeOf(TypeReference type) : base(OpCode.SizeOf)
public SizeOf(IType type) : base(OpCode.SizeOf)
{
this.type = type;
}
readonly TypeReference type;
readonly IType type;
/// <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 void WriteTo(ITextOutput output)
{
@ -1911,7 +1911,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1911,7 +1911,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Load address of array element.</summary>
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.Index = index;
@ -1951,9 +1951,9 @@ namespace ICSharpCode.Decompiler.IL @@ -1951,9 +1951,9 @@ namespace ICSharpCode.Decompiler.IL
this.Array = this.array.Inline(flagsBefore, instructionStack, out finished);
return this;
}
readonly TypeReference type;
readonly IType type;
/// <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; } }
/// <summary>Gets whether the 'readonly' prefix was applied to this instruction.</summary>
public bool IsReadOnly { get; set; }

36
ICSharpCode.Decompiler/IL/Instructions.tt

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

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

@ -22,14 +22,14 @@ using System.Diagnostics; @@ -22,14 +22,14 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Mono.Cecil;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.Decompiler.Disassembler;
namespace ICSharpCode.Decompiler.IL
{
public abstract class CallInstruction : ILInstruction
{
public static CallInstruction Create(OpCode opCode, MethodReference method)
public static CallInstruction Create(OpCode opCode, IMethod method)
{
switch (opCode) {
case OpCode.Call:
@ -44,22 +44,15 @@ namespace ICSharpCode.Decompiler.IL @@ -44,22 +44,15 @@ namespace ICSharpCode.Decompiler.IL
}
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);
}
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 {
get {
if (OpCode == OpCode.NewObj)
@ -97,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL @@ -97,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets/Sets the type specified in the 'constrained.' prefix.
/// Returns null if no 'constrained.' prefix exists for this call.
/// </summary>
public TypeReference ConstrainedTo;
public IType ConstrainedTo;
public override void WriteTo(ITextOutput output)
{

8
ICSharpCode.Decompiler/ReferenceResolvingException.cs

@ -30,14 +30,14 @@ namespace ICSharpCode.Decompiler @@ -30,14 +30,14 @@ namespace ICSharpCode.Decompiler
public class ReferenceResolvingException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary>
public ReferenceResolvingException()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </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>
public ReferenceResolvingException(string message)
@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </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="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 @@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler
}
/// <summary>
/// Initializes a new instance of the <see cref="T:ResolveException"/> class
/// Initializes a new instance of the <see cref="ReferenceResolvingException"/> class
/// </summary>
/// <param name="info">The object that holds the serialized object data.</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 @@ -63,7 +63,8 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
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();
new Helpers.RemoveCompilerAttribute().Run(syntaxTree);

3
ILSpy.BamlDecompiler/Tests/TestRunner.cs

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

6
ILSpy/Languages/ILAstLanguage.cs

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

Loading…
Cancel
Save