@@ -109,6 +109,7 @@ static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterPar
109109
110110 if ( parameters . DeterministicMvid )
111111 module . Mvid = Guid . Empty ;
112+
112113 var metadata = new MetadataBuilder ( module , fq_name , timestamp , symbol_writer_provider ) ;
113114 try {
114115 module . metadata_builder = metadata ;
@@ -117,62 +118,21 @@ static void Write (ModuleDefinition module, Disposable<Stream> stream, WriterPar
117118 metadata . SetSymbolWriter ( symbol_writer ) ;
118119 BuildMetadata ( module , metadata ) ;
119120
121+ if ( parameters . DeterministicMvid )
122+ metadata . ComputeDeterministicMvid ( ) ;
123+
120124 var writer = ImageWriter . CreateWriter ( module , metadata , stream ) ;
121125 stream . value . SetLength ( 0 ) ;
122126 writer . WriteImage ( ) ;
123127
124128 if ( parameters . StrongNameKeyPair != null )
125129 CryptoService . StrongName ( stream . value , writer , parameters . StrongNameKeyPair ) ;
126- if ( parameters . DeterministicMvid ) {
127- module . Mvid = ComputeGuid ( stream . value ) ;
128- writer . PatchMvid ( module . Mvid ) ;
129- }
130130 }
131131 } finally {
132132 module . metadata_builder = null ;
133133 }
134134 }
135135
136- static void CopyStreamChunk ( Stream stream , Stream dest_stream , byte [ ] buffer , int length )
137- {
138- while ( length > 0 ) {
139- int read = stream . Read ( buffer , 0 , System . Math . Min ( buffer . Length , length ) ) ;
140- dest_stream . Write ( buffer , 0 , read ) ;
141- length -= read ;
142- }
143- }
144-
145- static byte [ ] ComputeHash ( Stream stream )
146- {
147- const int buffer_size = 8192 ;
148-
149- var sha1 = new SHA1Managed ( ) ;
150-
151- stream . Seek ( 0 , SeekOrigin . Begin ) ;
152- var buffer = new byte [ buffer_size ] ;
153-
154- using ( var crypto_stream = new CryptoStream ( Stream . Null , sha1 , CryptoStreamMode . Write ) )
155- CopyStreamChunk ( stream , crypto_stream , buffer , ( int ) stream . Length ) ;
156- return sha1 . Hash ;
157- }
158-
159- static unsafe Guid ComputeGuid ( Stream stream )
160- {
161- byte [ ] hashCode = ComputeHash ( stream ) ;
162-
163- // From corefx/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs
164- Guid guid = default ( Guid ) ;
165- byte * guidPtr = ( byte * ) & guid ;
166- for ( var i = 0 ; i < 16 ; i ++ ) {
167- guidPtr [ i ] = hashCode [ i ] ;
168- }
169- // modify the guid data so it decodes to the form of a "random" guid ala rfc4122
170- guidPtr [ 7 ] = ( byte ) ( ( guidPtr [ 7 ] & 0x0f ) | ( 4 << 4 ) ) ;
171- guidPtr [ 8 ] = ( byte ) ( ( guidPtr [ 8 ] & 0x3f ) | ( 2 << 6 ) ) ;
172-
173- return guid ;
174- }
175-
176136 static void BuildMetadata ( ModuleDefinition module , MetadataBuilder metadata )
177137 {
178138 if ( ! module . HasImage ) {
@@ -1559,12 +1519,20 @@ void AddConstraints (GenericParameter generic_parameter, GenericParamConstraintT
15591519 {
15601520 var constraints = generic_parameter . Constraints ;
15611521
1562- var rid = generic_parameter . token . RID ;
1522+ var gp_rid = generic_parameter . token . RID ;
1523+
1524+ for ( int i = 0 ; i < constraints . Count ; i ++ ) {
1525+ var constraint = constraints [ i ] ;
1526+
1527+ var rid = table . AddRow ( new GenericParamConstraintRow (
1528+ gp_rid ,
1529+ MakeCodedRID ( GetTypeToken ( constraint . ConstraintType ) , CodedIndex . TypeDefOrRef ) ) ) ;
1530+
1531+ constraint . token = new MetadataToken ( TokenType . GenericParamConstraint , rid ) ;
15631532
1564- for ( int i = 0 ; i < constraints . Count ; i ++ )
1565- table . AddRow ( new GenericParamConstraintRow (
1566- rid ,
1567- MakeCodedRID ( GetTypeToken ( constraints [ i ] ) , CodedIndex . TypeDefOrRef ) ) ) ;
1533+ if ( constraint . HasCustomAttributes )
1534+ AddCustomAttributes ( constraint ) ;
1535+ }
15681536 }
15691537
15701538 void AddInterfaces ( TypeDefinition type )
@@ -2690,6 +2658,25 @@ void AddSequencePoints (MethodDebugInformation info)
26902658
26912659 method_debug_information_table . rows [ rid - 1 ] . Col2 = GetBlobIndex ( signature ) ;
26922660 }
2661+
2662+ public void ComputeDeterministicMvid ( )
2663+ {
2664+ var guid = CryptoService . ComputeGuid ( CryptoService . ComputeHash (
2665+ data ,
2666+ resources ,
2667+ string_heap ,
2668+ user_string_heap ,
2669+ blob_heap ,
2670+ table_heap ,
2671+ code ) ) ;
2672+
2673+ var position = guid_heap . position ;
2674+ guid_heap . position = 0 ;
2675+ guid_heap . WriteBytes ( guid . ToByteArray ( ) ) ;
2676+ guid_heap . position = position ;
2677+
2678+ module . Mvid = guid ;
2679+ }
26932680 }
26942681
26952682 sealed class SignatureWriter : ByteBuffer {
0 commit comments