/// <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); } } } }
/// <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); } } }