[Mono.Debugger.Soft] Improved ILInterpreter to eval properties that return a primitiv...
authorJeffrey Stedfast <jeff@xamarin.com>
Tue, 10 Jun 2014 19:15:56 +0000 (15:15 -0400)
committerJeffrey Stedfast <jeff@xamarin.com>
Tue, 10 Jun 2014 19:16:36 +0000 (15:16 -0400)
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/ILInterpreter.cs

index e0175f36bdfe9ee6adacf79dc0c25723a9c9e99d..d004991988badb05163fb20f0d57f366da2773b6 100644 (file)
@@ -23,8 +23,13 @@ namespace Mono.Debugger.Soft
                        // IL_0008:  br         IL_000d
                        // IL_000d:  ldloc.0
                        // IL_000e:  ret
+                       // ... or returns a simple constant:
+                       // IL_0000:  ldc.i4 1024
+                       // IL_0005:  conv.i8
+                       // IL_0006:  ret
                        if (args != null && args.Length != 0)
-                               throw new NotSupportedException ();                             
+                               throw new NotSupportedException ();
+
                        if (method.IsStatic || method.DeclaringType.IsValueType || this_val == null || !(this_val is ObjectMirror))
                                throw new NotSupportedException ();
 
@@ -32,58 +37,333 @@ namespace Mono.Debugger.Soft
                        if (instructions.Count > 16)
                                throw new NotSupportedException ();
 
-                       Value[] stack = new Value [16];
+                       var stack = new Value [16];
+                       var ins = instructions [0];
                        Value locals_0 = null;
-                       Value res = null;
-
-                       int sp = 0;
                        int ins_count = 0;
-                       var ins = instructions [0];
+                       int sp = 0;
+
                        while (ins != null) {
                                if (ins_count > 16)
                                        throw new NotImplementedException ();
-                               ins_count ++;
+
                                var next = ins.Next;
+                               ins_count++;
 
                                var op = ins.OpCode;
                                if (op == OpCodes.Nop) {
                                } else if (op == OpCodes.Ldarg_0) {
-                                       if (sp > 0)
+                                       if (sp != 0)
                                                throw new NotSupportedException ();
+
                                        stack [sp++] = this_val;
                                } else if (op == OpCodes.Ldfld) {
                                        if (sp != 1)
                                                throw new NotSupportedException ();
-                                       var obj = (ObjectMirror)stack [--sp];
-                                       var field = (FieldInfoMirror)ins.Operand;
+
+                                       var obj = (ObjectMirror) stack [--sp];
+                                       var field = (FieldInfoMirror) ins.Operand;
                                        try {
                                                stack [sp++] = obj.GetValue (field);
                                        } catch (ArgumentException) {
                                                throw new NotSupportedException ();
                                        }
+                               } else if (op == OpCodes.Ldc_I4_0) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 0);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_1) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 1);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_2) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 2);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_3) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 3);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_4) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 4);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_5) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 5);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_6) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 6);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_7) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 7);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_8) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, 8);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_M1) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, -1);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I4_S) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_I8) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_R4) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Ldc_R8) {
+                                       if (sp != 0)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, ins.Operand);
+                                       } catch (ArgumentException) {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_I) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_I1) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToSByte (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_U1) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToByte (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_I2) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt16 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_U2) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt16 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_I4) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_U4) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt32 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_I8) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToInt64 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_U8) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt64 (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_R4) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToSingle (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
+                               } else if (op == OpCodes.Conv_R8) {
+                                       if (sp != 1)
+                                               throw new NotSupportedException ();
+
+                                       try {
+                                               var primitive = (PrimitiveValue) stack [--sp];
+                                               stack [sp++] = new PrimitiveValue (method.VirtualMachine, Convert.ToDouble (primitive.Value));
+                                       } catch {
+                                               throw new NotSupportedException ();
+                                       }
                                } else if (op == OpCodes.Stloc_0) {
                                        if (sp != 1)
                                                throw new NotSupportedException ();
+
                                        locals_0 = stack [--sp];
                                } else if (op == OpCodes.Br) {
-                                       next = (ILInstruction)ins.Operand;
+                                       next = (ILInstruction) ins.Operand;
                                } else if (op == OpCodes.Ldloc_0) {
                                        if (sp != 0)
                                                throw new NotSupportedException ();
+
                                        stack [sp++] = locals_0;
                                } else if (op == OpCodes.Ret) {
-                                       if (sp == 0)
-                                               res = null;
-                                       else
-                                               res = stack [--sp];
-                                       break;
+                                       if (sp > 0) {
+                                               var res = stack [--sp];
+
+                                               var primitive = res as PrimitiveValue;
+                                               if (method.ReturnType.IsPrimitive && primitive != null) {
+                                                       // cast the primitive value to the return type
+                                                       try {
+                                                               switch (method.ReturnType.CSharpName) {
+                                                               case "double": res = new PrimitiveValue (method.VirtualMachine, Convert.ToDouble (primitive.Value)); break;
+                                                               case "float": res = new PrimitiveValue (method.VirtualMachine, Convert.ToSingle (primitive.Value)); break;
+                                                               case "ulong": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt64 (primitive.Value)); break;
+                                                               case "long": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt64 (primitive.Value)); break;
+                                                               case "uint": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt32 (primitive.Value)); break;
+                                                               case "int": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt32 (primitive.Value)); break;
+                                                               case "ushort": res = new PrimitiveValue (method.VirtualMachine, Convert.ToUInt16 (primitive.Value)); break;
+                                                               case "short": res = new PrimitiveValue (method.VirtualMachine, Convert.ToInt16 (primitive.Value)); break;
+                                                               case "sbyte": res = new PrimitiveValue (method.VirtualMachine, Convert.ToSByte (primitive.Value)); break;
+                                                               case "byte": res = new PrimitiveValue (method.VirtualMachine, Convert.ToByte (primitive.Value)); break;
+                                                               case "char": res = new PrimitiveValue (method.VirtualMachine, Convert.ToChar (primitive.Value)); break;
+                                                               case "bool": res = new PrimitiveValue (method.VirtualMachine, Convert.ToBoolean (primitive.Value)); break;
+                                                               }
+                                                       } catch {
+                                                               throw new NotSupportedException ();
+                                                       }
+                                               }
+
+                                               return res;
+                                       }
+
+                                       return null;
                                } else {
                                        throw new NotSupportedException ();
                                }
+
                                ins = next;
                        }
 
-                       return res;
+                       return null;
                }
        }
 }