diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 47c6b6751..982183d95 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -37,6 +37,7 @@ namespace Decompiler public int PushCount; public string Name { get { return "IL_" + this.Offset.ToString("X2"); } } public ByteCode Next; + public Instruction[] Prefixes; // Non-null only if needed public List StackBefore; public List StoreTo; @@ -57,7 +58,14 @@ namespace Decompiler public override string ToString() { StringBuilder sb = new StringBuilder(); - sb.AppendFormat("{0}:{1} {2} ", this.Name, this.Label != null ? " *" : "", this.Code.GetName()); + sb.AppendFormat("{0}:{1} ", this.Name, this.Label != null ? " *" : ""); + if (this.Prefixes != null) { + foreach (var prefix in this.Prefixes) { + sb.Append(prefix.OpCode.Name); + sb.Append(' '); + } + } + sb.Append(this.Code.GetName()); if (this.Operand is ILLabel) { sb.Append(((ILLabel)this.Operand).Name); } else if (this.Operand is ILLabel[]) { @@ -126,7 +134,14 @@ namespace Decompiler { // Create temporary structure for the stack analysis List body = new List(methodDef.Body.Instructions.Count); + List prefixes = null; foreach(Instruction inst in methodDef.Body.Instructions) { + if (inst.OpCode.OpCodeType == OpCodeType.Prefix) { + if (prefixes == null) + prefixes = new List(1); + prefixes.Add(inst); + continue; + } ILCode code = (ILCode)inst.OpCode.Code; object operand = inst.Operand; ILCodeUtil.ExpandMacro(ref code, ref operand, methodDef.Body); @@ -138,6 +153,11 @@ namespace Decompiler PopCount = inst.GetPopCount(), PushCount = inst.GetPushCount() }; + if (prefixes != null) { + byteCode.Offset = prefixes[0].Offset; + byteCode.Prefixes = prefixes.ToArray(); + prefixes = null; + } instrToByteCode[inst] = byteCode; body.Add(byteCode); } @@ -420,6 +440,7 @@ namespace Decompiler ILExpression expr = new ILExpression(byteCode.Code, byteCode.Operand); expr.ILRanges.Add(ilRange); + expr.Prefixes = byteCode.Prefixes; // Label for this instruction if (byteCode.Label != null) { diff --git a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs index fcaf1e85c..0b94ba5d4 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs @@ -199,6 +199,7 @@ namespace Decompiler public ILCode Code { get; set; } public object Operand { get; set; } public List Arguments { get; set; } + public Instruction[] Prefixes { get; set; } // Mapping to the original instructions (useful for debugging) public List ILRanges { get; set; } @@ -212,6 +213,18 @@ namespace Decompiler this.ILRanges = new List(1); } + public Instruction GetPrefix(Code code) + { + var prefixes = this.Prefixes; + if (prefixes != null) { + foreach (Instruction i in prefixes) { + if (i.OpCode.Code == code) + return i; + } + } + return null; + } + public override IEnumerable GetChildren() { return Arguments; @@ -272,6 +285,13 @@ namespace Decompiler } } + if (this.Prefixes != null) { + foreach (Instruction prefix in this.Prefixes) { + output.Write(prefix.OpCode.Name); + output.Write(' '); + } + } + output.Write(Code.GetName()); if (this.InferredType != null) { output.Write(':'); diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 4f99002ce..202ea5a1a 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -160,10 +160,15 @@ namespace Decompiler MethodReference method = (MethodReference)expr.Operand; if (forceInferChildren) { for (int i = 0; i < expr.Arguments.Count; i++) { - if (i == 0 && method.HasThis) - InferTypeForExpression(expr.Arguments[i], method.DeclaringType); - else + if (i == 0 && method.HasThis) { + Instruction constraint = expr.GetPrefix(Code.Constrained); + if (constraint != null) + InferTypeForExpression(expr.Arguments[i], new ByReferenceType((TypeReference)constraint.Operand)); + else + InferTypeForExpression(expr.Arguments[i], method.DeclaringType); + } else { InferTypeForExpression(expr.Arguments[i], SubstituteTypeArgs(method.Parameters[method.HasThis ? i - 1: i].ParameterType, method)); + } } } return SubstituteTypeArgs(method.ReturnType, method);