/// <summary>
 /// Returns the first node representing of the specified constructor - full-depth search.
 /// </summary>
 /// <value>Searches the complete tree looking for the node.</value>
 /// <param name="inf">The constructor to search for.</param>
 /// <returns>The first node representing of the specified constructor - full-depth search.</returns>
 public StaticConstructorDependency this[ConstructorInfo inf]
 {
     get
     {
         if (TheConstructor == inf)
         {
             return(this);
         }
         else
         {
             List <StaticConstructorDependency> posDeps = (from deps in Children
                                                           where (deps.TheConstructor.Equals(inf))
                                                           select deps).ToList();
             if (posDeps.Count > 0)
             {
                 return(posDeps.First());
             }
             else
             {
                 foreach (StaticConstructorDependency child in Children)
                 {
                     StaticConstructorDependency posDep = child[inf];
                     if (posDep != null)
                     {
                         return(posDep);
                     }
                 }
                 return(null);
             }
         }
     }
 }
예제 #2
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);
                }
            }
        }