Exemplo n.º 1
0
        // ...
        /// <summary>
        /// Emit a global method "MibcConfig" that will contain key-value settings in the following format:
        ///   ldstr "key1"
        ///   ldstr "value1"
        ///   pop
        ///   pop
        ///   ldstr "key2"
        ///   ldstr "value2"
        ///   pop
        ///   pop
        ///   ...
        /// </summary>
        public static void GenerateConfigData(MibcConfig config, TypeSystemMetadataEmitter emitter)
        {
            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            foreach (FieldInfo mibcCfgField in typeof(MibcConfig).GetFields())
            {
                Debug.Assert(!mibcCfgField.IsStatic && mibcCfgField.FieldType == typeof(string));
                il.LoadString(emitter.GetUserStringHandle(mibcCfgField.Name));
                il.LoadString(emitter.GetUserStringHandle((string)mibcCfgField.GetValue(config) ?? ""));
                il.OpCode(ILOpCode.Pop);
                il.OpCode(ILOpCode.Pop);
            }
            il.OpCode(ILOpCode.Ret);
            emitter.AddGlobalMethod(nameof(MibcConfig), il, 8);
        }
Exemplo n.º 2
0
        public static int GenerateMibcFile(MibcConfig config, TypeSystemContext tsc, FileInfo outputFileName, IEnumerable <MethodProfileData> methodsToAttemptToPlaceIntoProfileData, bool validate, bool uncompressed)
        {
            TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyName(outputFileName.Name), tsc);

            emitter.InjectSystemPrivateCanon();
            emitter.AllowUseOfAddGlobalMethod();

            if (config != null)
            {
                GenerateConfigData(config, emitter);
            }

            SortedDictionary <string, MIbcGroup> groups     = new SortedDictionary <string, MIbcGroup>();
            StringBuilder    mibcGroupNameBuilder           = new StringBuilder();
            HashSet <string> assembliesAssociatedWithMethod = new HashSet <string>();

            foreach (var entry in methodsToAttemptToPlaceIntoProfileData)
            {
                MethodDesc method = entry.Method;
                assembliesAssociatedWithMethod.Clear();
                AddAssembliesAssociatedWithMethod(method, assembliesAssociatedWithMethod, out string definingAssembly);

                string[] assemblyNames = new string[assembliesAssociatedWithMethod.Count];
                int      i             = 1;
                assemblyNames[0] = definingAssembly;

                foreach (string s in assembliesAssociatedWithMethod)
                {
                    if (s.Equals(definingAssembly))
                    {
                        continue;
                    }
                    assemblyNames[i++] = s;
                }

                // Always keep the defining assembly as the first name
                Array.Sort(assemblyNames, 1, assemblyNames.Length - 1);
                mibcGroupNameBuilder.Clear();
                foreach (string s in assemblyNames)
                {
                    mibcGroupNameBuilder.Append(s);
                    mibcGroupNameBuilder.Append(';');
                }

                string mibcGroupName = mibcGroupNameBuilder.ToString();
                if (!groups.TryGetValue(mibcGroupName, out MIbcGroup mibcGroup))
                {
                    mibcGroup = new MIbcGroup(mibcGroupName, emitter);
                    groups.Add(mibcGroupName, mibcGroup);
                }
                mibcGroup.AddProcessedMethodData(entry);
            }

            var buffer = new BlobBuilder();
            var il     = new InstructionEncoder(buffer);

            foreach (var entry in groups)
            {
                il.LoadString(emitter.GetUserStringHandle(entry.Key));
                il.OpCode(ILOpCode.Ldtoken);
                il.Token(entry.Value.EmitMethod());
                il.OpCode(ILOpCode.Pop);
            }

            emitter.AddGlobalMethod("AssemblyDictionary", il, 8);
            MemoryStream peFile = new MemoryStream();

            emitter.SerializeToStream(peFile);
            peFile.Position = 0;

            if (outputFileName.Exists)
            {
                outputFileName.Delete();
            }

            if (uncompressed)
            {
                using (FileStream file = new FileStream(outputFileName.FullName, FileMode.Create))
                {
                    peFile.CopyTo(file);
                }
            }
            else
            {
                using (ZipArchive file = ZipFile.Open(outputFileName.FullName, ZipArchiveMode.Create))
                {
                    var entry = file.CreateEntry(outputFileName.Name + ".dll", CompressionLevel.Optimal);
                    using (Stream archiveStream = entry.Open())
                    {
                        peFile.CopyTo(archiveStream);
                    }
                }
            }

            Program.PrintMessage($"Generated {outputFileName.FullName}");

            if (validate)
            {
                return(ValidateMIbcData(tsc, outputFileName, peFile.ToArray(), methodsToAttemptToPlaceIntoProfileData));
            }
            else
            {
                return(0);
            }
        }