using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.IO; using System.Globalization; using System.Xml; using System.Diagnostics; using Indy.IL2CPU.IL; namespace Indy.IL2CPU.Compiler.Old { public class CompilerHelper { //public class CacheState: IComparable, IEquatable { // public List UsedGenericMethods = new List(); // public List UsedGenericTypes = new List(); // internal void Load(string aFile) // { // if (!File.Exists(aFile)) // { // return; // } // var xDoc = new XmlDocument(); // xDoc.Load(aFile); // var xElemMethods = xDoc.SelectSingleNode("/CacheState/GenericMethods"); // foreach (XmlNode xMethodNode in xElemMethods.ChildNodes) // { // UsedGenericMethods.Add(xMethodNode.InnerText); // } // var xElemTypes = xDoc.SelectSingleNode("/CacheState/GenericTypes"); // foreach (XmlNode xTypeNode in xElemTypes.ChildNodes) // { // UsedGenericTypes.Add(xTypeNode.InnerText); // } // UsedGenericTypes.Sort(); // UsedGenericMethods.Sort(); // } // internal void Save(string aFile) // { // using (var xOut = XmlWriter.Create(aFile)) // { // xOut.WriteStartDocument(); // xOut.WriteStartElement("CacheState"); // { // xOut.WriteStartElement("GenericMethods"); // { // foreach (var xMethod in UsedGenericMethods) // { // xOut.WriteStartElement("Method"); // { // xOut.WriteCData(xMethod); // } // xOut.WriteEndElement(); // } // } xOut.WriteEndElement(); // xOut.WriteStartElement("GenericTypes"); // { // foreach (var xType in UsedGenericTypes) // { // xOut.WriteStartElement("Type"); // { // xOut.WriteCData(xType); // } // xOut.WriteEndElement(); // } // } xOut.WriteEndElement(); // } // xOut.WriteEndElement(); // xOut.WriteEndDocument(); // } // } // #region IComparable Members // public int CompareTo(CacheState other) // { // var xResult = this.UsedGenericMethods.Count.CompareTo(other.UsedGenericMethods.Count); // if (xResult != 0) // { // return xResult; // } // xResult = this.UsedGenericTypes.Count.CompareTo(other.UsedGenericTypes.Count); // if (xResult != 0) // { // return xResult; // } // for (int i = 0; i < UsedGenericMethods.Count; i++) // { // xResult = UsedGenericMethods[i].CompareTo(other.UsedGenericMethods[i]); // if (xResult != 0) // { // return xResult; // } // } // for (int i = 0; i < UsedGenericTypes.Count; i++) // { // xResult = UsedGenericTypes[i].CompareTo(other.UsedGenericTypes[i]); // if (xResult != 0) // { // return xResult; // } // } // return 0; // } // #endregion // #region IEquatable Members // public bool Equals(CacheState other) // { // return CompareTo(other) == 0; // } // #endregion //} //public List SkipList //{ // get; // set; //} //public event Func GetCacheStateFile; //public event Func GetChecksumFile; //public event Func GetAssembler; //public event Action SaveAssembler; //public event Func GetOpCodeMap; //public event Action DebugLog; //public List Plugs = new List(); //public CompilerHelper() //{ // SkipList = new List(); //} //private Assembly mEntryAssembly; //private IEnumerable mAllAssemblies; //public void CompileExe(Assembly aAssembly) //{ // if (aAssembly == null) // { // throw new ArgumentNullException("aAssembly"); // } // mEntryAssembly=aAssembly; // mAllAssemblies = Scanner.GetAllAssemblies(aAssembly, SkipList); // var xAssembliesToScanForGenerics = GetAssembliesToScanForGenerics(mAllAssemblies); // LoadCacheStates(mAllAssemblies); // bool xNeedsFullRecompile = false; // // now scan for generics usage // foreach (var xAsm in xAssembliesToScanForGenerics) // { // var xTest = this.ScanAssembly(xAsm); // if(!xTest.Equals(mCacheStates[xAsm])){ // mCacheStates[xAsm] = xTest; // xNeedsFullRecompile =true; // } // } // if (xNeedsFullRecompile) // { // foreach(var xAsm in mAllAssemblies) // { // if(!mGenericTypeInstancesToGenerate.ContainsKey(xAsm)) // { // ScanAssembly(xAsm); // } // } // DoFullRecompile(); // } // else // { // SmartRecompile(); // } //} //private void CompileAssembly(Assembly aAssembly) //{ // if(aAssembly==null) // { // throw new ArgumentNullException("aAssembly"); // } // Console.Write(new String('-', Console.BufferWidth)); // Console.WriteLine("Starting compilation of assembly: " + aAssembly.FullName); // var xCompiler = new AssemblyCompiler(); // xCompiler.DebugLog = delegate(LogSeverityEnum aSeverity, string aMessage) { this.DebugLog(aSeverity, aMessage); }; // xCompiler.IsEntrypointAssembly = aAssembly == mEntryAssembly; // using (var xAssembler = GetAssembler(aAssembly, xCompiler.IsEntrypointAssembly)) // { // xCompiler.Assembler = xAssembler; // xCompiler.Assembly = aAssembly; // if (xCompiler.IsEntrypointAssembly) // { // foreach (var xRef in mAllAssemblies) // { // xCompiler.AssemblyReferences.Add(xRef.FullName); // } // } // xCompiler.OpCodeMap = GetOpCodeMap(); // xCompiler.Plugs.AddRange(Plugs); // if(!mGenericTypeInstancesToGenerate.ContainsKey(aAssembly)) // { // Console.Write(""); // } // xCompiler.Types.AddRange(mGenericTypeInstancesToGenerate[aAssembly]); // xCompiler.Methods.AddRange(mGenericMethodInstancesToGenerate[aAssembly]); // try // { // xCompiler.Execute(); // // update cache state files // mCacheStates[aAssembly].Save(GetCacheStateFile(aAssembly)); // var xLastTime = File.GetLastWriteTimeUtc(aAssembly.Location).ToBinary(); // var xChecksumFileName = GetChecksumFile(aAssembly); // File.WriteAllText(xChecksumFileName, xLastTime.ToString()); // } // finally // { // // todo: at the end, we dont want this, but for now to do debugging, leave it in finally // SaveAssembler(aAssembly, xCompiler.Assembler); // } // } // GC.Collect(); //} ////HACK fix up Generics //private List Convert(IEnumerable source) //{ // List result = new List(); // foreach (var method in source) // result.Add(method.MethodHandle); // return result; //} //private void DoFullRecompile() //{ // int xTest = 0; // foreach (var xAsm in mAllAssemblies) // { // CompileAssembly(xAsm); // xTest++; // GC.Collect(); // if (xTest == 2) // { // return; // } // } //} //private void SmartRecompile() //{ // foreach (var xAsm in GetAssembliesToScanForGenerics(mAllAssemblies)) // { // CompileAssembly(xAsm); // } //} //private void LoadCacheStates(IEnumerable xAllAssemblies) //{ // mCacheStates.Clear(); // foreach (var xAsm in xAllAssemblies) // { // var xState = new CacheState(); // xState.Load(GetCacheStateFile(xAsm)); // mCacheStates.Add(xAsm, xState); // } //} //private Dictionary mCacheStates = new Dictionary(); //private Dictionary> mGenericTypeInstancesToGenerate = new Dictionary>(); //private Dictionary> mGenericMethodInstancesToGenerate = new Dictionary>(); //private CacheState ScanAssembly(Assembly aAsm) //{ // var xResult = new CacheState(); // bool xShouldSkipMain = aAsm == mEntryAssembly; // if (!mGenericTypeInstancesToGenerate.ContainsKey(aAsm)) // { // mGenericTypeInstancesToGenerate.Add(aAsm, new List()); // } // var xDeclaringType_TypeInstances = mGenericTypeInstancesToGenerate[aAsm]; // if (!mGenericMethodInstancesToGenerate.ContainsKey(aAsm)) // { // mGenericMethodInstancesToGenerate.Add(aAsm, new List()); // } // var xDeclaringType_MethodInstances = mGenericMethodInstancesToGenerate[aAsm]; // Action xCheckType = null; // xCheckType = new Action(delegate(Type aType) // { // if(aType==null) // { // Console.Write(""); // } // if (aType.IsGenericType && !aType.IsGenericTypeDefinition) // { // // add to the list of the current assembly // if (!xResult.UsedGenericTypes.Contains(aType.AssemblyQualifiedName)) // { // xResult.UsedGenericTypes.Add(aType.AssemblyQualifiedName); // } // // add to the list of the declaring assembly, so it can generate it later on // if (!xDeclaringType_TypeInstances.Contains(aType)) // { // xDeclaringType_TypeInstances.Add(aType); // } // foreach (var xArg in aType.GetGenericArguments()) // { // xCheckType(xArg); // } // } // }); // foreach (var xType in aAsm.GetTypes()) // { // if (xType.BaseType != null) // { // xCheckType(xType.BaseType); // } // foreach (var xMethod in xType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) // { // if (xShouldSkipMain && xMethod == aAsm.EntryPoint) // { // continue; // } // xCheckType(xMethod.ReturnType); // foreach (var xParam in xMethod.GetParameters()) // { // xCheckType(xParam.ParameterType); // } // try // { // if (xMethod.GetMethodBody() == null) // { // continue; // } // } // catch (System.Security.VerificationException VE) // { // // apparently, ms uses some scary code for the .net framework.. // continue; // } // catch (Exception E) // { // throw; // } // var xReader = new ILReader(xMethod); // while (xReader.Read()) // { // switch (xReader.OpCode) // { // case OpCodeEnum.Call: // case OpCodeEnum.Callvirt: // case OpCodeEnum.Newobj: // if (xReader.OperandValueMethod.DeclaringType == null) // { // // todo: what to do? // break; // } // xCheckType(xReader.OperandValueMethod.DeclaringType); // if (xReader.OperandValueMethod.IsGenericMethod && !xReader.OperandValueMethod.IsGenericMethodDefinition) // { // var xName = xReader.OperandValueMethod.GetFullName(); // if (!xResult.UsedGenericMethods.Contains(xName)) // { // xResult.UsedGenericMethods.Add(xName); // } // // add to the list of the declaring assembly, so it can generate it later on // if (!xDeclaringType_MethodInstances.Contains(xReader.OperandValueMethod)) // { // xDeclaringType_MethodInstances.Add(xReader.OperandValueMethod); // } // } // break; // } // } // } // } // return xResult; //} //private List GetAssembliesToScanForGenerics(IEnumerable xAllAssemblies) //{ // var xAssembliesToScanForGenerics = new List(); // foreach (var xAsm in xAllAssemblies) // { // var xLastTime = File.GetLastWriteTimeUtc(xAsm.Location).ToBinary(); // var xChecksumFileName = GetChecksumFile(xAsm); // if (File.Exists(xChecksumFileName)) // { // var xChecksumStr = File.ReadAllText(xChecksumFileName); // long xChecksum; // if (Int64.TryParse(xChecksumStr, out xChecksum)) // { // if (xChecksum == xLastTime) // { // // todo: remove or move to other logging // Console.WriteLine("Assembly '{0}' doesn't need a recompile", xAsm.GetName().Name); // continue; // } // } // } // xAssembliesToScanForGenerics.Add(xAsm); // } // return xAssembliesToScanForGenerics; //} } }