[mcs] Make compiler output deterministic. Fixes #26842
authorMarek Safar <marek.safar@gmail.com>
Wed, 18 Feb 2015 19:01:05 +0000 (20:01 +0100)
committerMarek Safar <marek.safar@gmail.com>
Wed, 18 Feb 2015 19:02:31 +0000 (20:02 +0100)
external/ikvm
mcs/mcs/ikvm.cs
mcs/mcs/module.cs

index 7e0b99936bf92502f7f63d43865cbbe771d3873b..d589df6e8a206e28b84304a75917006a0e076c29 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7e0b99936bf92502f7f63d43865cbbe771d3873b
+Subproject commit d589df6e8a206e28b84304a75917006a0e076c29
index 3bf9599a3d591559f084f7663165ddd4d7e82f03..da6b0c11ab56b9ab6eda6b3123dff78bbf71082a 100644 (file)
@@ -246,7 +246,10 @@ namespace Mono.CSharp
                        : base (compiler)
                {
                        this.importer = importer;
-                       domain = new Universe (UniverseOptions.MetadataOnly | UniverseOptions.ResolveMissingMembers | UniverseOptions.DisableFusion | UniverseOptions.DecodeVersionInfoAttributeBlobs);
+                       domain = new Universe (UniverseOptions.MetadataOnly | UniverseOptions.ResolveMissingMembers | 
+                               UniverseOptions.DisableFusion | UniverseOptions.DecodeVersionInfoAttributeBlobs |
+                               UniverseOptions.DeterministicOutput);
+                       
                        domain.AssemblyResolve += AssemblyReferenceResolver;
                        loaded_names = new List<Tuple<AssemblyName, string, Assembly>> ();
 
index 7175dc388551c13146d8fa527f15d72b8992ac35..3a9377c7547bc94531acc0df743eeb868d2e07e7 100644 (file)
@@ -17,6 +17,8 @@ using System.Runtime.InteropServices;
 using Mono.CompilerServices.SymbolWriter;
 using System.Linq;
 using System.IO;
+using System.Security.Cryptography;
+using Mono.Security.Cryptography;
 
 #if STATIC
 using IKVM.Reflection;
@@ -40,13 +42,14 @@ namespace Mono.CSharp
                sealed class StaticDataContainer : CompilerGeneratedContainer
                {
                        readonly Dictionary<int, Struct> size_types;
-                       int fields;
+                       readonly Dictionary<string, FieldSpec> data_hashes;
 
                        public StaticDataContainer (ModuleContainer module)
-                               : base (module, new MemberName ("<PrivateImplementationDetails>" + module.builder.ModuleVersionId.ToString ("B"), Location.Null),
+                               : base (module, new MemberName ("<PrivateImplementationDetails>", Location.Null),
                                        Modifiers.STATIC | Modifiers.INTERNAL)
                        {
                                size_types = new Dictionary<int, Struct> ();
+                               data_hashes = new Dictionary<string, FieldSpec> (StringComparer.Ordinal);
                        }
 
                        public override void CloseContainer ()
@@ -77,13 +80,27 @@ namespace Mono.CSharp
                                        size_type.TypeBuilder.__SetLayout (1, data.Length);
                                }
 
-                               var name = "$field-" + fields.ToString ("X");
-                               ++fields;
-                               const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL;
-                               var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
-                               fbuilder.__SetDataAndRVA (data);
+                               FieldSpec fs;
+                               var data_hash = GenerateDataFieldName (data);
+                               if (!data_hashes.TryGetValue (data_hash, out fs)) {
+                                       var name = "$field-" + data_hash;
+                                       const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.READONLY;
+                                       var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
+                                       fbuilder.__SetDataAndRVA (data);
 
-                               return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
+                                       fs = new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
+                                       data_hashes.Add (data_hash, fs);
+                               }
+
+                               return fs;
+                       }
+
+                       static string GenerateDataFieldName (byte[] bytes)
+                       {
+                               using (var hashProvider = new SHA1CryptoServiceProvider ())
+                               {
+                                       return CryptoConvert.ToHex (hashProvider.ComputeHash (bytes));
+                               }
                        }
                }