Browse Source

Store prefixes with their parent instruction in ILAst; make use of 'constrained' prefix in type analysis.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
ecd8bc7cce
  1. 23
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  2. 20
      ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  3. 11
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

23
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -37,6 +37,7 @@ namespace Decompiler @@ -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<StackSlot> StackBefore;
public List<ILVariable> StoreTo;
@ -57,7 +58,14 @@ namespace Decompiler @@ -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 @@ -126,7 +134,14 @@ namespace Decompiler
{
// Create temporary structure for the stack analysis
List<ByteCode> body = new List<ByteCode>(methodDef.Body.Instructions.Count);
List<Instruction> prefixes = null;
foreach(Instruction inst in methodDef.Body.Instructions) {
if (inst.OpCode.OpCodeType == OpCodeType.Prefix) {
if (prefixes == null)
prefixes = new List<Instruction>(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 @@ -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 @@ -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) {

20
ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -199,6 +199,7 @@ namespace Decompiler @@ -199,6 +199,7 @@ namespace Decompiler
public ILCode Code { get; set; }
public object Operand { get; set; }
public List<ILExpression> Arguments { get; set; }
public Instruction[] Prefixes { get; set; }
// Mapping to the original instructions (useful for debugging)
public List<ILRange> ILRanges { get; set; }
@ -212,6 +213,18 @@ namespace Decompiler @@ -212,6 +213,18 @@ namespace Decompiler
this.ILRanges = new List<ILRange>(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<ILNode> GetChildren()
{
return Arguments;
@ -272,6 +285,13 @@ namespace Decompiler @@ -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(':');

11
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -160,10 +160,15 @@ namespace Decompiler @@ -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);

Loading…
Cancel
Save