Example #1
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.sizeOnStackInBytes == 4 && itemB.sizeOnStackInBytes == 4)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false,
                    isValue = true
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 && itemB.sizeOnStackInBytes == 8)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false,
                    isValue = true
                });
            }
            else
            {
                throw new NotSupportedException("Unsupported number of bytes for compare equal to!");
            }
        }
Example #2
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem itemToConvert = conversionState.CurrentStackFrame.Stack.Pop();
            int numBytesToConvertTo = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Conv_U:
                    numBytesToConvertTo = 4;
                    break;
                case OpCodes.Conv_U1:
                    numBytesToConvertTo = 1;
                    break;
                case OpCodes.Conv_U2:
                    numBytesToConvertTo = 2;
                    break;
                case OpCodes.Conv_U4:
                    numBytesToConvertTo = 4;
                    break;
                case OpCodes.Conv_U8:
                    numBytesToConvertTo = 8;
                    break;
            }

            bool pushEDX = numBytesToConvertTo == 8;

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = (pushEDX ? 8 : 4),
                isFloat = false,
                isGCManaged = false
            });
        }
Example #3
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
            
            bool valueisFloat = Utilities.IsFloat(theField.FieldType);
            Types.TypeInfo fieldTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
            int stackSize = fieldTypeInfo.SizeOnStackInBytes;
            
            StackItem objPointer = conversionState.CurrentStackFrame.Stack.Pop();

            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldflda)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false
                });
            }
            else
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = valueisFloat,
                    sizeOnStackInBytes = stackSize,
                    isGCManaged = fieldTypeInfo.IsGCManaged
                });
            }
        }
Example #4
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
     FieldInfo theField = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
     
     switch ((OpCodes)theOp.opCode.Value)
     {
         case OpCodes.Ldsfld:
             {
                 Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theField.FieldType);
                 int size = theTypeInfo.SizeOnStackInBytes;
                 bool isFloat = Utilities.IsFloat(theField.FieldType);
                 
                 conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                 {
                     isFloat = isFloat,
                     sizeOnStackInBytes = (size == 8 ? 8 : 4),
                     isGCManaged = theTypeInfo.IsGCManaged,
                     isValue = theTypeInfo.IsValueType
                 });
             }
             break;
         case OpCodes.Ldsflda:
             conversionState.CurrentStackFrame.Stack.Push(new StackItem()
             {
                 isFloat = false,
                 sizeOnStackInBytes = 4,
                 isGCManaged = false,
                 isValue = false
             });
             break;
     }
 }
Example #5
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase constructorMethod = theOp.MethodToCall;
            Type objectType = constructorMethod.DeclaringType;

            if (typeof(Delegate).IsAssignableFrom(objectType))
            {
                StackItem funcPtrItem = conversionState.CurrentStackFrame.Stack.Pop(); ;
                conversionState.CurrentStackFrame.Stack.Pop();
                conversionState.CurrentStackFrame.Stack.Push(funcPtrItem);
                return;
            }

            Types.MethodInfo constructorMethodInfo = conversionState.TheILLibrary.GetMethodInfo(constructorMethod);

            ParameterInfo[] allParams = constructorMethod.GetParameters();
            foreach (ParameterInfo aParam in allParams)
            {
                conversionState.CurrentStackFrame.Stack.Pop();
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = 4,
                isNewGCObject = true,
                isGCManaged = true,
                isValue = false
            });
        }
Example #6
0
File: Sub.cs Project: kztao/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.sizeOnStackInBytes == 4 &&
                itemB.sizeOnStackInBytes == 4)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 &&
                itemB.sizeOnStackInBytes == 8)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 8,
                    isGCManaged = false
                });
            }
        }
Example #7
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.sizeOnStackInBytes == 4 &&
                itemB.sizeOnStackInBytes == 4)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false,
                    isValue = itemA.isValue && itemB.isValue
                });
            }
            else if (itemA.sizeOnStackInBytes == 8 &&
                itemB.sizeOnStackInBytes == 8)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    isNewGCObject = false,
                    sizeOnStackInBytes = 8,
                    isGCManaged = false,
                    isValue = itemA.isValue && itemB.isValue
                });
            }
        }
Example #8
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem addressItem = conversionState.CurrentStackFrame.Stack.Pop();
            int bytesToLoad = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Ldind_U1:
                case OpCodes.Ldind_I1:
                    bytesToLoad = 1;
                    break;
                case OpCodes.Ldind_U2:
                case OpCodes.Ldind_I2:
                    bytesToLoad = 2;
                    break;
                case OpCodes.Ldind_U4:
                case OpCodes.Ldind_I4:
                case OpCodes.Ldind_I:
                    bytesToLoad = 4;
                    break;
                case OpCodes.Ldind_I8:
                    bytesToLoad = 8;
                    break;
                case OpCodes.Ldind_Ref:
                    bytesToLoad = Options.AddressSizeInBytes;
                    break;
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = bytesToLoad == 8 ? 8 : 4,
                isFloat = false,
                isGCManaged = false
            });
        }
Example #9
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            Int16 index = 0;
            switch ((OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Ldarg:
                    index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                    break;
                case OpCodes.Ldarg_0:
                    index = 0;
                    break;
                case OpCodes.Ldarg_1:
                    index = 1;
                    break;
                case OpCodes.Ldarg_2:
                    index = 2;
                    break;
                case OpCodes.Ldarg_3:
                    index = 3;
                    break;
                case OpCodes.Ldarg_S:
                    index = (Int16)theOp.ValueBytes[0];
                    break;
                case OpCodes.Ldarga:
                    index = Utilities.ReadInt16(theOp.ValueBytes, 0);
                    break;
                case OpCodes.Ldarga_S:
                    index = (Int16)theOp.ValueBytes[0];
                    break;
            }

            List<Type> allParams = conversionState.Input.TheMethodInfo.UnderlyingInfo.GetParameters().Select(x => x.ParameterType).ToList();
            if (!conversionState.Input.TheMethodInfo.IsStatic)
            {
                allParams.Insert(0, conversionState.Input.TheMethodInfo.UnderlyingInfo.DeclaringType);
            }
            
            if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga ||
                (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = 4,
                    isFloat = false,
                    isGCManaged = false
                });
            }
            else
            {
                Types.TypeInfo paramTypeInfo = conversionState.TheILLibrary.GetTypeInfo(allParams[index]);
                int bytesForArg = paramTypeInfo.SizeOnStackInBytes;
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    sizeOnStackInBytes = bytesForArg,
                    isFloat = false,
                    isGCManaged = paramTypeInfo.IsGCManaged
                });
            }
        }
Example #10
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            MethodBase methodToCall = theOp.MethodToCall;
            Types.MethodInfo methodToCallInfo = conversionState.TheILLibrary.GetMethodInfo(methodToCall);

            if (methodToCall is MethodInfo)
            {
                Type retType = ((MethodInfo)methodToCall).ReturnType;
                Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
                StackItem returnItem = new StackItem()
                {
                    isFloat = Utilities.IsFloat(retType),
                    sizeOnStackInBytes = retTypeInfo.SizeOnStackInBytes,
                    isGCManaged = retTypeInfo.IsGCManaged,
                    isValue = retTypeInfo.IsValueType
                };
                
                int bytesToAdd = 0;
                List<Type> allParams = ((MethodInfo)methodToCall).GetParameters().Select(x => x.ParameterType).ToList();
                if (!methodToCall.IsStatic)
                {
                    allParams.Insert(0, methodToCall.DeclaringType);
                }
                foreach (Type aParam in allParams)
                {
                    conversionState.CurrentStackFrame.Stack.Pop();
                    bytesToAdd += conversionState.TheILLibrary.GetTypeInfo(aParam).SizeOnStackInBytes;
                }
                if (bytesToAdd > 0)
                {
                    if (returnItem.sizeOnStackInBytes != 0)
                    {
                        conversionState.CurrentStackFrame.Stack.Push(returnItem);
                    }
                }
                else if (returnItem.sizeOnStackInBytes != 0)
                {
                    conversionState.CurrentStackFrame.Stack.Push(returnItem);
                }
            }
            else if (methodToCall is ConstructorInfo)
            {
                ConstructorInfo aConstructor = (ConstructorInfo)methodToCall;
                if (aConstructor.IsStatic)
                {
                    //Static constructors do not have parameters or return values
                }
                else
                {
                    ParameterInfo[] allParams = methodToCall.GetParameters();
                    foreach (ParameterInfo aParam in allParams)
                    {
                        conversionState.CurrentStackFrame.Stack.Pop();
                    }
                }
            }
        }
Example #11
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     conversionState.CurrentStackFrame.Stack.Push(new StackItem()
     {
         isFloat = false,
         sizeOnStackInBytes = 4,
         isGCManaged = false
     });
 }
Example #12
0
 public override void Preprocess(ILPreprocessState preprocessState, ILOp theOp)
 {
     for (int i = 0; i < theOp.ValueBytes.Length / 4; i++)
     {
         int branchOffset = theOp.NextOffset + Utilities.ReadInt32(theOp.ValueBytes, i * 4);
         ILOp opToGoTo = preprocessState.Input.At(branchOffset);
         opToGoTo.LabelRequired = true;
     }
 }
Example #13
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     Int16 index = 0;
     switch ((OpCodes)theOp.opCode.Value)
     {
         case OpCodes.Ldarg:
             index = Utilities.ReadInt16(theOp.ValueBytes, 0);
             break;
         case OpCodes.Ldarg_0:
             index = 0;
             break;
         case OpCodes.Ldarg_1:
             index = 1;
             break;
         case OpCodes.Ldarg_2:
             index = 2;
             break;
         case OpCodes.Ldarg_3:
             index = 3;
             break;
         case OpCodes.Ldarg_S:
             index = (Int16)theOp.ValueBytes[0];
             break;
         case OpCodes.Ldarga:
             index = Utilities.ReadInt16(theOp.ValueBytes, 0);
             break;
         case OpCodes.Ldarga_S:
             index = (Int16)theOp.ValueBytes[0];
             break;
     }
                 
     if ((OpCodes)theOp.opCode.Value == OpCodes.Ldarga ||
         (OpCodes)theOp.opCode.Value == OpCodes.Ldarga_S)
     {
         conversionState.CurrentStackFrame.Stack.Push(new StackItem()
         {
             sizeOnStackInBytes = 4,
             isFloat = false,
             isGCManaged = false,
             isValue = false
         });
     }
     else
     {
         Types.VariableInfo argInfo = conversionState.Input.TheMethodInfo.ArgumentInfos[index];
         Types.TypeInfo paramTypeInfo = argInfo.TheTypeInfo;
         int bytesForArg = paramTypeInfo.SizeOnStackInBytes;
         conversionState.CurrentStackFrame.Stack.Push(new StackItem()
         {
             sizeOnStackInBytes = bytesForArg,
             isFloat = false,
             isGCManaged = paramTypeInfo.IsGCManaged,
             isValue = paramTypeInfo.IsValueType
         });
     }
 }
Example #14
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     Type retType = (conversionState.Input.TheMethodInfo.IsConstructor ?
         typeof(void) : ((MethodInfo)conversionState.Input.TheMethodInfo.UnderlyingInfo).ReturnType);
     Types.TypeInfo retTypeInfo = conversionState.TheILLibrary.GetTypeInfo(retType);
     if (retTypeInfo.SizeOnStackInBytes != 0)
     {
         conversionState.CurrentStackFrame.Stack.Pop();
     }
 }
Example #15
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            bool loadAddr = (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca ||
                            (ILOp.OpCodes)theOp.opCode.Value == OpCodes.Ldloca_S;
            UInt16 localIndex = 0;
            switch ((ILOp.OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Ldloc:
                case OpCodes.Ldloca:
                    localIndex = (UInt16)Utilities.ReadInt16(theOp.ValueBytes, 0);
                    break;
                case OpCodes.Ldloc_0:
                    localIndex = 0;
                    break;
                case OpCodes.Ldloc_1:
                    localIndex = 1;
                    break;
                case OpCodes.Ldloc_2:
                    localIndex = 2;
                    break;
                case OpCodes.Ldloc_3:
                    localIndex = 3;
                    break;
                case OpCodes.Ldloc_S:
                case OpCodes.Ldloca_S:
                    localIndex = (UInt16)theOp.ValueBytes[0];
                    break;
            }

            Types.VariableInfo theLoc = conversionState.Input.TheMethodInfo.LocalInfos.ElementAt(localIndex);
            
            if (loadAddr)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false,
                    isValue = false
                });
            }
            else
            {
                int pushedLocalSizeVal = theLoc.TheTypeInfo.SizeOnStackInBytes;

                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = Utilities.IsFloat(theLoc.UnderlyingType),
                    sizeOnStackInBytes = pushedLocalSizeVal,
                    isGCManaged = theLoc.TheTypeInfo.IsGCManaged,
                    isValue = theLoc.TheTypeInfo.IsValueType
                });
            }
        }
Example #16
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
            Type theType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
            Types.TypeInfo theTypeInfo = conversionState.TheILLibrary.GetTypeInfo(theType);
            int size = theTypeInfo.SizeOnStackInBytes;

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = false,
                sizeOnStackInBytes = size,
                isGCManaged = false
            });
        }
Example #17
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     try
     {
         conversionState.CurrentStackFrame.Stack.Push(new StackItem()
         {
             isFloat = false,
             sizeOnStackInBytes = 4,
             isGCManaged = false
         });
     }
     catch
     {
         throw new NotSupportedException("The metadata token specifies a fieldref or methodref which isn't supported yet!");
     }
 }
Example #18
0
File: Dup.cs Project: kztao/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged = itemA.isGCManaged
            });
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                isFloat = itemA.isFloat,
                sizeOnStackInBytes = itemA.sizeOnStackInBytes,
                isGCManaged = itemA.isGCManaged
            });
        }
Example #19
0
        public override void Preprocess(ILPreprocessState preprocessState, ILOp theOp)
        {
            Types.MethodInfo methodInfo = preprocessState.TheILLibrary.GetMethodInfo(theOp.MethodToCall);

            if (theOp.LoadAtILOpAfterOp != null)
            {
                ILBlock anILBlock = preprocessState.TheILLibrary.GetILBlock(methodInfo);
                int index = anILBlock.ILOps.IndexOf(theOp.LoadAtILOpAfterOp);
                index++;
                anILBlock.ILOps[index].LabelRequired = true;
            }
            else if (theOp.LoadAtILOffset != int.MaxValue)
            {
                int offset = theOp.LoadAtILOffset;
                ILOp theLoadedOp = preprocessState.TheILLibrary.GetILBlock(methodInfo).At(offset);
                theLoadedOp.LabelRequired = true;
            }
        }
Example #20
0
 private static void rotateStackItems(ILPreprocessState state, int items, int distance)
 {
     if (distance >= items)
     {
         throw new IndexOutOfRangeException("IlPreprocessor.rotateStackItems: distance >= items invalid!");
     }
     List<StackItem> poppedItems = new List<StackItem>();
     for (int i = 0; i < items; i++)
     {
         poppedItems.Add(state.CurrentStackFrame.Stack.Pop());
     }
     for (int i = distance; i > -1; i--)
     {
         state.CurrentStackFrame.Stack.Push(poppedItems[i]);
     }
     for (int i = items - 1; i > distance; i--)
     {
         state.CurrentStackFrame.Stack.Push(poppedItems[i]);
     }
 }
Example #21
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     rotateStackItems(conversionState, theOp.StackSwitch_Items, 1);
 }
Example #22
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     //Weirdly this is not a true/false returning op - it actually returns a null or object ref.
 } 
Example #23
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     base.PerformStackOperations(conversionState, theOp);
 }
Example #24
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     conversionState.CurrentStackFrame.Stack.Pop();
 }
Example #25
0
 public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
 {
     //No effect
 }
Example #26
0
File: Shr.cs Project: kztao/FlingOS
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            //Pop in reverse order to push
            StackItem itemB = conversionState.CurrentStackFrame.Stack.Pop();
            StackItem itemA = conversionState.CurrentStackFrame.Stack.Pop();

            if (itemA.sizeOnStackInBytes == 4 &&
                itemB.sizeOnStackInBytes == 4)
            {
                conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                {
                    isFloat = false,
                    sizeOnStackInBytes = 4,
                    isGCManaged = false
                });
            }
            else if ((itemA.sizeOnStackInBytes == 8 &&
                itemB.sizeOnStackInBytes == 4))
            {
                if ((OpCodes)theOp.opCode.Value == OpCodes.Shr_Un)
                {
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged = false
                    });
                }
                else
                {
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged = false
                    });
                }
            }
            else if (itemA.sizeOnStackInBytes == 8 &&
                itemB.sizeOnStackInBytes == 8)
            {
                if ((OpCodes)theOp.opCode.Value == OpCodes.Shr_Un)
                {
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged = false
                    });
                }
                else
                {
                    conversionState.CurrentStackFrame.Stack.Push(new StackItem()
                    {
                        isFloat = false,
                        sizeOnStackInBytes = 8,
                        isGCManaged = false
                    });
                }
            }
        }
Example #27
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            bool isFloat = false;
            int numBytes = 0;

            switch ((OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Ldc_I4:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_0:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_1:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_2:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_3:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_4:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_5:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_6:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_7:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_8:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_M1:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I4_S:
                    numBytes = 4;
                    break;
                case OpCodes.Ldc_I8:
                    numBytes = 8;
                    break;
                case OpCodes.Ldc_R4:
                    numBytes = 4;
                    isFloat = true;
                    break;
                case OpCodes.Ldc_R8:
                    numBytes = 8;
                    isFloat = true;
                    break;
            }

            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = numBytes,
                isFloat = isFloat,
                isGCManaged = false,
                isValue = true
            });
        }
Example #28
0
        public override void PerformStackOperations(ILPreprocessState conversionState, ILOp theOp)
        {
            Type elementType = null;
            bool pushValue = true;
            int sizeToPush = 4;
            bool isFloat = false;

            switch ((OpCodes)theOp.opCode.Value)
            {
                case OpCodes.Ldelem:
                    {
                        int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                        elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
                    }
                    break;

                case OpCodes.Ldelema:
                    {
                        int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                        elementType = conversionState.Input.TheMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);

                        pushValue = false;
                    }
                    break;

                case OpCodes.Ldelem_R4:
                case OpCodes.Ldelem_R8:
                    throw new NotSupportedException("Ldelem op variant not supported yet!");

                case OpCodes.Ldelem_I1:
                    sizeToPush = 1;
                    elementType = typeof(sbyte);
                    break;
                case OpCodes.Ldelem_I2:
                    sizeToPush = 2;
                    elementType = typeof(Int16);
                    break;

                case OpCodes.Ldelem_U1:
                    sizeToPush = 1;
                    elementType = typeof(byte);
                    break;
                case OpCodes.Ldelem_U2:
                    sizeToPush = 2;
                    elementType = typeof(UInt16);
                    break;

                case OpCodes.Ldelem_Ref:
                    elementType = null;
                    break;

                case OpCodes.Ldelem_U4:
                    elementType = typeof(UInt32);
                    break;

                case OpCodes.Ldelem_I4:
                    elementType = typeof(Int32);
                    break;

                case OpCodes.Ldelem_I8:
                    sizeToPush = 8;
                    elementType = typeof(Int64);
                    break;
            }

            Types.TypeInfo elemTypeInfo = elementType == null ? null : conversionState.TheILLibrary.GetTypeInfo(elementType);

            //      5.2. Pop index and array ref from our stack
            conversionState.CurrentStackFrame.Stack.Pop();
            conversionState.CurrentStackFrame.Stack.Pop();
            //      5.3. Push element onto our stack
            conversionState.CurrentStackFrame.Stack.Push(new StackItem()
            {
                sizeOnStackInBytes = sizeToPush > 4 ? 8 : 4,
                isFloat = isFloat,
                isNewGCObject = false,
                isGCManaged = pushValue ? (elementType == null || elemTypeInfo.IsGCManaged) : false,
                isValue = pushValue ? (elementType != null && elemTypeInfo.IsValueType) : false
            });
        }
Example #29
0
        /// <summary>
        /// Injects the garbage collector related IL ops into the specified method.
        /// </summary>
        /// <param name="TheLibrary">The library being compiled.</param>
        /// <param name="theMethodInfo">The method to inject ops into.</param>
        /// <param name="theILBlock">The IL block for the method to inject ops into.</param>
        private static void InjectGC(ILLibrary TheLibrary, Types.MethodInfo theMethodInfo, ILBlock theILBlock)
        {
            if (theMethodInfo.ApplyGC)
            {
                // Find the index of the MethodStart op
                int MethodStartOpPos = theILBlock.PositionOf(theILBlock.ILOps.Where(x => x is ILOps.MethodStart).First());

                // Inject ops for incrementing ref. count of args at start of method
                int InjectIncArgsRefCountPos = MethodStartOpPos + 1;
                foreach (Types.VariableInfo argInfo in theMethodInfo.ArgumentInfos)
                {
                    if (argInfo.TheTypeInfo.IsGCManaged)
                    {
                        theILBlock.ILOps.Insert(InjectIncArgsRefCountPos, new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Ldarg,
                            ValueBytes = BitConverter.GetBytes(argInfo.Position)
                        });
                        theILBlock.ILOps.Insert(InjectIncArgsRefCountPos + 1, new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Call,
                            MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.IncrementRefCountMethodAttribute)].First().UnderlyingInfo
                        });
                    }
                }

                // The following two things can be done within the same loop:
                
                // Inject ops for inc./dec. ref. counts of objects when written to:
                //      - Arguments / Locals
                //      - Fields / Static Fields
                //      - Elements of Arrays

                // Add Cleanup Block and Inject finally-block ops for it
                //      - Also remember the op for storing return value (if any)

                ILPreprocessState preprocessState = new ILPreprocessState()
                {
                    TheILLibrary = TheLibrary,
                    Input = theILBlock,
                    CurrentStackFrame = new StackFrame()
                };

                ExceptionHandledBlock CleanupExBlock = new ExceptionHandledBlock();
                
                for (int opIndx = 0; opIndx < theILBlock.ILOps.Count; opIndx++)
                {
                    ILOp currOp = theILBlock.ILOps[opIndx];
                    bool IncRefCount = false;
                    int incOpIndexBy = 0;
                    
                    switch ((ILOp.OpCodes)currOp.opCode.Value)
                    {
                        case ILOp.OpCodes.Stsfld:
                            #region Stsfld
                            {
                                int metadataToken = Utilities.ReadInt32(currOp.ValueBytes, 0);
                                System.Reflection.FieldInfo theField = theMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
                                Types.TypeInfo theFieldTypeInfo = TheLibrary.GetTypeInfo(theField.FieldType);
                                if (theFieldTypeInfo.IsGCManaged)
                                {
                                    theILBlock.ILOps.Insert(opIndx, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Ldsfld,
                                        ValueBytes = currOp.ValueBytes
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 1, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                    });
                                    
                                    IncRefCount = true;
                                    incOpIndexBy = 2;
                                }
                            }
                            #endregion
                            break;
                        case ILOp.OpCodes.Stloc:
                        case ILOp.OpCodes.Stloc_0:
                        case ILOp.OpCodes.Stloc_1:
                        case ILOp.OpCodes.Stloc_2:
                        case ILOp.OpCodes.Stloc_3:
                        case ILOp.OpCodes.Stloc_S:
                            #region Stloc
                            {
                                UInt16 localIndex = 0;
                                switch ((ILOp.OpCodes)currOp.opCode.Value)
                                {
                                    case ILOp.OpCodes.Stloc:
                                        localIndex = (UInt16)Utilities.ReadInt16(currOp.ValueBytes, 0);
                                        break;
                                    case ILOp.OpCodes.Stloc_0:
                                        localIndex = 0;
                                        break;
                                    case ILOp.OpCodes.Stloc_1:
                                        localIndex = 1;
                                        break;
                                    case ILOp.OpCodes.Stloc_2:
                                        localIndex = 2;
                                        break;
                                    case ILOp.OpCodes.Stloc_3:
                                        localIndex = 3;
                                        break;
                                    case ILOp.OpCodes.Stloc_S:
                                        localIndex = (UInt16)currOp.ValueBytes[0];
                                        break;
                                }
                                Types.TypeInfo LocalTypeInfo = theMethodInfo.LocalInfos[localIndex].TheTypeInfo;
                                if (LocalTypeInfo.IsGCManaged)
                                {
                                    theILBlock.ILOps.Insert(opIndx, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Ldloc,
                                        ValueBytes = BitConverter.GetBytes(localIndex)
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 1, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                    });
                                    
                                    IncRefCount = true;
                                    incOpIndexBy = 2;
                                }
                            }
                            #endregion
                            break;
                        case ILOp.OpCodes.Stfld:
                            #region Stfld
                            {
                                int metadataToken = Utilities.ReadInt32(currOp.ValueBytes, 0);
                                System.Reflection.FieldInfo theField = theMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
                                Types.TypeInfo theFieldTypeInfo = TheLibrary.GetTypeInfo(theField.FieldType);
                                if (theFieldTypeInfo.IsGCManaged)
                                {
                                    // Items on stack:
                                    //  - Object reference
                                    //  - (New) Value to store
                                    //
                                    // We want to load the current value of the field
                                    //  for which we must duplicate the object ref
                                    // But first, we must remove the (new) value to store
                                    //  off the stack, while also storing it to put back
                                    //  on the stack after so the store can continue
                                    //
                                    // So:
                                    //      1. Switch value to store and object ref on stack
                                    //      3. Duplicate the object ref
                                    //      4. Load the field value
                                    //      5. Call dec ref count
                                    //      6. Switch value to store and object ref back again

                                    //USE A SWITCH STACK ITEMS OP!!

                                    theILBlock.ILOps.Insert(opIndx, new ILOps.StackSwitch()
                                    {
                                        StackSwitch_Items = 2
                                    });
                                    
                                    theILBlock.ILOps.Insert(opIndx + 1, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Dup
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 2, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Ldfld,
                                        ValueBytes = currOp.ValueBytes
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 3, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                    });

                                    theILBlock.ILOps.Insert(opIndx + 4, new ILOps.StackSwitch()
                                    {
                                        StackSwitch_Items = 2
                                    });

                                    IncRefCount = true;
                                    incOpIndexBy = 5;
                                }
                            }
                            #endregion
                            break;
                        case ILOp.OpCodes.Stelem:
                        case ILOp.OpCodes.Stelem_Ref:
                            #region Stelem / Stelem_Ref
                            {
                                bool doDecrement = false;
                                bool isRefOp = false;
                                if ((ILOp.OpCodes)currOp.opCode.Value == ILOp.OpCodes.Stelem_Ref)
                                {
                                    doDecrement = preprocessState.CurrentStackFrame.Stack.Peek().isGCManaged;
                                    isRefOp = true;
                                }
                                else
                                {
                                    int metadataToken = Utilities.ReadInt32(currOp.ValueBytes, 0);
                                    Type elementType = theMethodInfo.UnderlyingInfo.Module.ResolveType(metadataToken);
                                    doDecrement = TheLibrary.GetTypeInfo(elementType).IsGCManaged;
                                }

                                if (doDecrement)
                                {
                                    // Items on stack:
                                    //  - Array reference
                                    //  - Index
                                    //  - (New) Value to store
                                    //
                                    // We want to load the current value of the element at Index in the array
                                    //  for which we must duplicate the array ref and index
                                    // But first, we must remove the (new) value to store
                                    //  off the stack, while also storing it to put back
                                    //  on the stack after so the store can continue
                                    //
                                    // So:
                                    //      1. Switch (rotate) 1 times the top 3 values so that index is on top
                                    //      2. Duplicate the index
                                    //      3. Switch (rotate) 2 times the top 4 values so that array ref is on top
                                    //      4. Duplicate the array ref
                                    //      5. Switch (rotate) 4 times the top 5 values so that duplicate array ref and index are on top
                                    //      6. Do LdElem op to load existing element value
                                    //      7. Call GC.DecrementRefCount
                                    //      8. Switch (rotate) 1 times the top 3 values so that the stack is in its original state
                                    //      (9. Continue to increment ref count as normal)
                                    //
                                    // The following is a diagram of the stack manipulation occurring here:
                                    //      Key: A=Array ref, I=Index, V=Value to store, E=Loaded element
                                    //      Top-most stack item appears last
                                    //  
                                    //     1) Rotate x 1    2) Duplicate       3)  Rot x 2         4)  Dup
                                    //  A,I,V ---------> V,A,I ---------> V,A,I,I ---------> I,I,V,A ---------> I,I,V,A,A
                                    //
                                    //
                                    //          5) Rot x 4           6) Ldelem        7) Call GC (Dec)
                                    //  I,I,V,A,A ---------> I,V,A,A,I ---------> I,V,A,E ---------> I,V,A
                                    //
                                    //
                                    //      8) Rot x 1       9)  Dup         10) Call GC (Inc)
                                    //  I,V,A ---------> A,I,V ---------> A,I,V,V ---------> A,I,V

                                    #region 1.
                                    theILBlock.ILOps.Insert(opIndx, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(3),
                                        StackSwitch_Items = 3
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 2.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Dup
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 3.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(4),
                                        StackSwitch_Items = 4
                                    });
                                    incOpIndexBy++;

                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(4),
                                        StackSwitch_Items = 4
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 4.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Dup
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 5.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(5),
                                        StackSwitch_Items = 5
                                    });
                                    incOpIndexBy++;
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(5),
                                        StackSwitch_Items = 5
                                    });
                                    incOpIndexBy++;
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(5),
                                        StackSwitch_Items = 5
                                    });
                                    incOpIndexBy++;
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(5),
                                        StackSwitch_Items = 5
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 6.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                                    {
                                        opCode = isRefOp ? System.Reflection.Emit.OpCodes.Ldelem_Ref : System.Reflection.Emit.OpCodes.Ldelem,
                                        ValueBytes = currOp.ValueBytes
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 7.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                    });
                                    incOpIndexBy++;
                                    #endregion
                                    #region 8.
                                    theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOps.StackSwitch()
                                    {
                                        ValueBytes = BitConverter.GetBytes(3),
                                        StackSwitch_Items = 3
                                    });
                                    incOpIndexBy++;
                                    #endregion

                                    IncRefCount = true;
                                }
                            }
                            #endregion
                            break;
                        case ILOp.OpCodes.Starg:
                        case ILOp.OpCodes.Starg_S:
                            #region Starg
                            {
                                UInt16 index = (ILOp.OpCodes)currOp.opCode.Value == ILOp.OpCodes.Starg_S ? 
                                    (UInt16)currOp.ValueBytes[0] : (UInt16)Utilities.ReadInt16(currOp.ValueBytes, 0);
                                if (theMethodInfo.ArgumentInfos[index].TheTypeInfo.IsGCManaged)
                                {
                                    theILBlock.ILOps.Insert(opIndx, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Ldarg,
                                        ValueBytes = BitConverter.GetBytes(index)
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 1, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Call,
                                        MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                    });

                                    IncRefCount = true;
                                    incOpIndexBy = 2;
                                }
                            }
                            #endregion
                            break;
                    }

                    if (IncRefCount &&
                        !preprocessState.CurrentStackFrame.Stack.Peek().isNewGCObject)
                    {
                        theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Dup
                        });
                        incOpIndexBy++;
                        theILBlock.ILOps.Insert(opIndx + incOpIndexBy, new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Call,
                            MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.IncrementRefCountMethodAttribute)].First().UnderlyingInfo
                        });
                        incOpIndexBy++;
                    }

                    // If op changed
                    if (theILBlock.ILOps[opIndx] != currOp)
                    {
                        theILBlock.ILOps[opIndx].Offset = currOp.Offset;
                        theILBlock.ILOps[opIndx].BytesSize = currOp.BytesSize;
                    }

                    // <= is correct. E.g. if 1 extra op added, incOpIndex=1 so <= results in currOp processed
                    //      + extra op processed
                    bool UseNextOpAsCleanupStart = false;
                    for (int i = 0; i <= incOpIndexBy; i++)
                    {
                        currOp = theILBlock.ILOps[opIndx];

                        if (UseNextOpAsCleanupStart)
                        {
                            UseNextOpAsCleanupStart = false;

                            CleanupExBlock.Offset = currOp.Offset;
                        }

                        if (currOp is ILOps.MethodStart)
                        {
                            TargetArchitecture.MethodStartOp.PerformStackOperations(preprocessState, theILBlock.ILOps[opIndx]);
                            UseNextOpAsCleanupStart = true;
                        }
                        else if (currOp is ILOps.MethodEnd)
                        {
                            TargetArchitecture.MethodEndOp.PerformStackOperations(preprocessState, theILBlock.ILOps[opIndx]);
                        }
                        else if (currOp is ILOps.StackSwitch)
                        {
                            TargetArchitecture.StackSwitchOp.PerformStackOperations(preprocessState, theILBlock.ILOps[opIndx]);
                        }
                        else
                        {
                            // Leave unsupported ops for the IL Scanner to deal with (or later code e.g. castclass op)
                            if (TargetArchitecture.TargetILOps.ContainsKey((ILOp.OpCodes)currOp.opCode.Value))
                            {
                                ILOp ConverterOp = TargetArchitecture.TargetILOps[(ILOp.OpCodes)currOp.opCode.Value];
                                ConverterOp.PerformStackOperations(preprocessState, currOp);
                            }
                        }

                        if (i > 0)
                        {
                            opIndx++;
                        }
                    }
                }

                if (theMethodInfo.ArgumentInfos.Count > 0 ||
                    theMethodInfo.LocalInfos.Count > 0)
                {
                    bool AddCleanupBlock = false;
                    foreach (Types.VariableInfo anArgInfo in theMethodInfo.ArgumentInfos)
                    {
                        if (anArgInfo.TheTypeInfo.IsGCManaged)
                        {
                            AddCleanupBlock = true;
                            break;
                        }
                    }
                    if (!AddCleanupBlock)
                    {
                        foreach (Types.VariableInfo aLocInfo in theMethodInfo.LocalInfos)
                        {
                            if (aLocInfo.TheTypeInfo.IsGCManaged)
                            {
                                AddCleanupBlock = true;
                                break;
                            }
                        }
                    }

                    if (AddCleanupBlock)
                    {
                        ILOp lastOp = theILBlock.ILOps.Last();
                        int lastOpOffset = lastOp.Offset;
                        int lastOpIndex = theILBlock.ILOps.Count - 1;
                        bool MethodHasReturnValue = false;

                        // If there is a return value, we will need to temp store it
                        if (theMethodInfo.UnderlyingInfo is System.Reflection.MethodInfo)
                        {
                            Type returnType = ((System.Reflection.MethodInfo)theMethodInfo.UnderlyingInfo).ReturnType;
                            //Void return type = no return value
                            if (returnType != typeof(void))
                            {
                                // Add local variable for storing return value
                                int lastLocalOffset = theMethodInfo.LocalInfos.Count > 0 ? theMethodInfo.LocalInfos.Last().Offset : 0;
                                int lastLocalSize = theMethodInfo.LocalInfos.Count > 0 ? theMethodInfo.LocalInfos.Last().TheTypeInfo.SizeOnStackInBytes : 0;
                                theMethodInfo.LocalInfos.Add(new Types.VariableInfo()
                                {
                                    UnderlyingType = returnType,
                                    TheTypeInfo = TheLibrary.GetTypeInfo(returnType),
                                    Position = theMethodInfo.LocalInfos.Count,
                                    Offset = lastLocalOffset + lastLocalSize
                                });

                                // Add op for storing return value, update op offsets
                                theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Stloc,
                                    Offset = lastOpOffset,
                                    BytesSize = lastOp.BytesSize,
                                    ValueBytes = BitConverter.GetBytes(theMethodInfo.LocalInfos.Count - 1)
                                });
                                lastOpIndex++;

                                MethodHasReturnValue = true;
                            }
                        }

                        ILOp leaveOp;
                        // Add the Leave op of the try-block
                        theILBlock.ILOps.Insert(lastOpIndex, leaveOp = new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Leave,
                            Offset = lastOpOffset,
                            BytesSize = lastOp.BytesSize,
                            ValueBytes = BitConverter.GetBytes(0)
                        });
                        lastOpIndex++;

                        FinallyBlock CleanupFinallyBlock = new FinallyBlock()
                        {
                            Offset = lastOpOffset + lastOp.BytesSize,
                            Length = 0
                        };
                        CleanupExBlock.Length = lastOpOffset - CleanupExBlock.Offset;
                        CleanupExBlock.FinallyBlocks.Add(CleanupFinallyBlock);

                        int cleanupOpsOffset = lastOpOffset + 1;

                        // Add cleanup code for local variables (including the return value local)
                        foreach (Types.VariableInfo aLocInfo in theMethodInfo.LocalInfos)
                        {
                            if (aLocInfo.TheTypeInfo.IsGCManaged)
                            {
                                theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Ldloc,
                                    Offset = cleanupOpsOffset,
                                    BytesSize = 1,
                                    ValueBytes = BitConverter.GetBytes(aLocInfo.Position)
                                });
                                cleanupOpsOffset++;
                                lastOpIndex++;

                                theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                    Offset = cleanupOpsOffset,
                                    BytesSize = 1,
                                    MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                });
                                cleanupOpsOffset++;
                                lastOpIndex++;

                                CleanupFinallyBlock.Length += 2;
                            }
                        }

                        // Add cleanup code for arguments
                        foreach (Types.VariableInfo anArgInfo in theMethodInfo.ArgumentInfos)
                        {
                            if (anArgInfo.TheTypeInfo.IsGCManaged)
                            {
                                theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Ldarg,
                                    Offset = cleanupOpsOffset,
                                    BytesSize = 1,
                                    ValueBytes = BitConverter.GetBytes(anArgInfo.Position)
                                });
                                cleanupOpsOffset++;
                                lastOpIndex++;

                                theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Call,
                                    Offset = cleanupOpsOffset,
                                    BytesSize = 1,
                                    MethodToCall = ILLibrary.SpecialMethods[typeof(Attributes.DecrementRefCountMethodAttribute)].First().UnderlyingInfo
                                });
                                cleanupOpsOffset++;
                                lastOpIndex++;

                                CleanupFinallyBlock.Length += 2;
                            }
                        }

                        // Add end finally op
                        theILBlock.ILOps.Insert(lastOpIndex, leaveOp.LoadAtILOpAfterOp = new ILOp()
                        {
                            opCode = System.Reflection.Emit.OpCodes.Endfinally,
                            Offset = cleanupOpsOffset,
                            BytesSize = 1
                        });
                        cleanupOpsOffset++;
                        lastOpIndex++;
                        
                        CleanupFinallyBlock.Length++;

                        // Add restore return value op
                        if (MethodHasReturnValue)
                        {
                            theILBlock.ILOps.Insert(lastOpIndex, new ILOp()
                            {
                                opCode = System.Reflection.Emit.OpCodes.Ldloc,
                                Offset = cleanupOpsOffset,
                                BytesSize = 1,
                                ValueBytes = BitConverter.GetBytes(theMethodInfo.LocalInfos.Count - 1)
                            });
                            cleanupOpsOffset++;
                            lastOpIndex++;
                        }

                        // Add ex block to the method
                        theILBlock.ExceptionHandledBlocks.Add(CleanupExBlock);

                        // Replace any Ret ops contained within Cleanup Block with:
                        //      - Op to store return value (if any)
                        //      - Leave op
                        bool Inside = false;
                        for(int opIndx = 0; opIndx < theILBlock.ILOps.Count; opIndx++)
                        {
                            if (theILBlock.ILOps[opIndx].Offset > CleanupExBlock.Offset + CleanupExBlock.Length)
                            {
                                break;
                            }
                            else if (theILBlock.ILOps[opIndx].Offset >= CleanupExBlock.Offset)
                            {
                                Inside = true;
                            }

                            if (Inside &&
                                (ILOp.OpCodes)theILBlock.ILOps[opIndx].opCode.Value == ILOp.OpCodes.Ret)
                            {
                                ILOp ARetOp = theILBlock.ILOps[opIndx];
                                theILBlock.ILOps.RemoveAt(opIndx);

                                if (MethodHasReturnValue)
                                {
                                    theILBlock.ILOps.Insert(opIndx, new ILOp()
                                    {
                                        opCode = System.Reflection.Emit.OpCodes.Stloc,
                                        Offset = ARetOp.Offset,
                                        ValueBytes = BitConverter.GetBytes(theMethodInfo.LocalInfos.Count - 1)
                                    });
                                    theILBlock.ILOps.Insert(opIndx + 1, new ILOp()
                                    {
                                        Offset = ARetOp.Offset,
                                        opCode = System.Reflection.Emit.OpCodes.Leave,
                                        ValueBytes = BitConverter.GetBytes(0),
                                        LoadAtILOpAfterOp = leaveOp.LoadAtILOpAfterOp
                                    });
                                }
                                else
                                {
                                    theILBlock.ILOps.Insert(opIndx, new ILOp()
                                    {
                                        Offset = ARetOp.Offset,
                                        opCode = System.Reflection.Emit.OpCodes.Leave,
                                        ValueBytes = BitConverter.GetBytes(0),
                                        LoadAtILOpAfterOp = leaveOp.LoadAtILOpAfterOp
                                    });
                                }
                            }
                        }
                    }
                }
            }
        }
Example #30
0
        /// <summary>
        /// Preprocesses the IL ops of the specified method/IL block.
        /// </summary>
        /// <param name="TheLibrary">The library being compiled.</param>
        /// <param name="theMethodInfo">The method to preprocess.</param>
        /// <param name="theILBlock">The IL block for the method to preprocess.</param>
        private static void PreprocessILOps(ILLibrary TheLibrary, Types.MethodInfo theMethodInfo, ILBlock theILBlock)
        {
            StaticConstructorDependency staticConstructorDependencyRoot = null;
            if (theMethodInfo.UnderlyingInfo is System.Reflection.ConstructorInfo &&
                        theMethodInfo.IsStatic)
            {
                System.Reflection.ConstructorInfo aConstructor = (System.Reflection.ConstructorInfo)theMethodInfo.UnderlyingInfo;
                staticConstructorDependencyRoot = ILLibrary.TheStaticConstructorDependencyTree[aConstructor];
                if (staticConstructorDependencyRoot == null)
                {
                    staticConstructorDependencyRoot = new StaticConstructorDependency()
                    {
                        TheConstructor = aConstructor
                    };
                    ILLibrary.TheStaticConstructorDependencyTree.Children.Add(staticConstructorDependencyRoot);
                }
            }

            ILPreprocessState preprosState = new ILPreprocessState()
            {
                TheILLibrary = TheLibrary,
                Input = theILBlock
            };

            for (int i = 0; i < theILBlock.ILOps.Count; i++)
            {
                ILOp theOp = theILBlock.ILOps[i];

                // Remove cast class ops
                if ((ILOp.OpCodes)theOp.opCode.Value == ILOp.OpCodes.Castclass)
                {
                    theILBlock.ILOps.RemoveAt(i);
                    i--;
                    continue;
                }
                else if ((ILOp.OpCodes)theOp.opCode.Value == ILOp.OpCodes.Call)
                {
                    if (theOp.MethodToCall != null && 
                        theOp.MethodToCall.DeclaringType.AssemblyQualifiedName.Contains("mscorlib"))
                    {
                        //We do not want to process ops which attempt to call methods in mscorlib!
                        theILBlock.ILOps.RemoveAt(i);
                        i--;

                        //We do not allow calls to methods declared in MSCorLib.
                        //Some of these calls can just be ignored (e.g. GetTypeFromHandle is
                        //  called by typeof operator).
                        //Ones which can't be ignored, will result in an error...by virtue of
                        //  the fact that they were ignored when they were required.

                        //But just to make sure we save ourselves a headache later when
                        //  runtime debugging, output a message saying we ignored the call.

                        // TODO - IL level comments
                        // result.ASM.AppendLine("; Call to method defined in MSCorLib ignored:"); // DEBUG INFO
                        // result.ASM.AppendLine("; " + anILOpInfo.MethodToCall.DeclaringType.FullName + "." + anILOpInfo.MethodToCall.Name); // DEBUG INFO

                        //If the method is a call to a constructor in MsCorLib:
                        if (theOp.MethodToCall is System.Reflection.ConstructorInfo)
                        {
                            //Then we can presume it was a call to a base-class constructor (e.g. the Object constructor)
                            //  and so we just need to remove any args that were loaded onto the stack.
                            // TODO: result.ASM.AppendLine("; Method to call was constructor so removing params"); // DEBUG INFO
                            
                            //Remove args from stack
                            //If the constructor was non-static, then the first arg is the instance reference.
                            if (!theOp.MethodToCall.IsStatic)
                            {
                                i++;
                                theILBlock.ILOps.Insert(i, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Pop
                                });
                            }
                            foreach (System.Reflection.ParameterInfo anInfo in theOp.MethodToCall.GetParameters())
                            {
                                i++;
                                theILBlock.ILOps.Insert(i, new ILOp()
                                {
                                    opCode = System.Reflection.Emit.OpCodes.Pop
                                });
                            }
                        }
                    }
                }

                try
                {
                    ILOp ConverterOp = TargetArchitecture.TargetILOps[(ILOp.OpCodes)theOp.opCode.Value];

                    ConverterOp.Preprocess(preprosState, theOp);

                    if (staticConstructorDependencyRoot != null)
                    {
                        //Create our static constructor dependency tree

                        //Each of these ops could try to access a static method or field
                        switch ((ILOp.OpCodes)theOp.opCode.Value)
                        {
                            case ILOp.OpCodes.Call:
                                //Check if the method to call is static and not a constructor itself
                                //If so, we must add the declaring type's static constructors to the tree
                                if(theOp.ValueBytes != null && theOp.ValueBytes.Length > 0)
                                {
                                    int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                                    System.Reflection.MethodBase methodBaseInf = theMethodInfo.UnderlyingInfo.Module.ResolveMethod(metadataToken);
                                    if (!(methodBaseInf.IsConstructor || methodBaseInf is System.Reflection.ConstructorInfo))
                                    {
                                        System.Reflection.MethodInfo methodInf = (System.Reflection.MethodInfo)methodBaseInf;
                                        System.Reflection.ConstructorInfo[] staticConstructors = 
                                            methodInf.DeclaringType.GetConstructors(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
                                                .Concat(methodInf.DeclaringType.GetConstructors(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))
                                                .ToArray();
                                        if (staticConstructors.Length > 0)
                                        {
                                            System.Reflection.ConstructorInfo TheConstructor = staticConstructors[0];
                                            if (staticConstructorDependencyRoot[TheConstructor] == null)
                                            {
                                                staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                                {
                                                    TheConstructor = TheConstructor
                                                });
                                            }
                                        }
                                    }
                                }
                                break;
                            case ILOp.OpCodes.Ldsfld:
                            case ILOp.OpCodes.Ldsflda:
                            case ILOp.OpCodes.Stsfld:
                                {
                                    int metadataToken = Utilities.ReadInt32(theOp.ValueBytes, 0);
                                    System.Reflection.FieldInfo fieldInf = theMethodInfo.UnderlyingInfo.Module.ResolveField(metadataToken);
                                    System.Reflection.ConstructorInfo[] staticConstructors = fieldInf.DeclaringType.GetConstructors(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
                                                                   .Concat(fieldInf.DeclaringType.GetConstructors(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))
                                                                   .ToArray();
                                    if (staticConstructors.Length > 0)
                                    {
                                        System.Reflection.ConstructorInfo TheConstructor = staticConstructors[0];
                                        if (staticConstructorDependencyRoot[TheConstructor] == null)
                                        {
                                            staticConstructorDependencyRoot.Children.Add(new StaticConstructorDependency()
                                            {
                                                TheConstructor = TheConstructor
                                            });
                                        }
                                    }
                                }
                                break;
                        }
                    }                    
                }
                catch (KeyNotFoundException)
                {
                    //Ignore - will be caught by Il scanner
                }
                catch (Exception ex)
                {
                    Logger.LogError("ILPRE", theILBlock.TheMethodInfo.ToString(), 0,
                        "Il Preprocessor error: PreprocessILOps: " + ex.Message);
                }
            }
        }