[linker] Both the TypeSpecification (T) along with the GenericArguments (G) must...
[mono.git] / mcs / tools / linker / Mono.Linker.Steps / MarkStep.cs
1 //
2 // MarkStep.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // (C) 2006 Jb Evain
8 // (C) 2007 Novell, Inc.
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections;
32 using System.Linq;
33
34 using Mono.Cecil;
35 using Mono.Cecil.Cil;
36
37 namespace Mono.Linker.Steps {
38
39         public class MarkStep : IStep {
40
41                 protected LinkContext _context;
42                 protected Queue _methods;
43                 protected ArrayList _virtual_methods;
44
45                 public AnnotationStore Annotations {
46                         get { return _context.Annotations; }
47                 }
48
49                 public MarkStep ()
50                 {
51                         _methods = new Queue ();
52                         _virtual_methods = new ArrayList ();
53                 }
54
55                 public virtual void Process (LinkContext context)
56                 {
57                         _context = context;
58
59                         Initialize ();
60                         Process ();
61                 }
62
63                 void Initialize ()
64                 {
65                         foreach (AssemblyDefinition assembly in _context.GetAssemblies ())
66                                 InitializeAssembly (assembly);
67                 }
68
69                 protected virtual void InitializeAssembly (AssemblyDefinition assembly)
70                 {
71                         MarkAssembly (assembly);
72                         foreach (TypeDefinition type in assembly.MainModule.Types) {
73                                 if (!Annotations.IsMarked (type))
74                                         continue;
75
76                                 InitializeType (type);
77                         }
78                 }
79
80                 void InitializeType (TypeDefinition type)
81                 {
82                         MarkType (type);
83
84                         if (type.HasFields)
85                                 InitializeFields (type);
86                         if (type.HasMethods)
87                                 InitializeMethods (type.Methods);
88
89                         if (type.HasNestedTypes) {
90                                 foreach (var nested in type.NestedTypes) {
91                                         if (Annotations.IsMarked (nested))
92                                                 InitializeType (nested);
93                                 }
94                         }
95                 }
96
97                 void InitializeFields (TypeDefinition type)
98                 {
99                         foreach (FieldDefinition field in type.Fields)
100                                 if (Annotations.IsMarked (field))
101                                         MarkField (field);
102                 }
103
104                 void InitializeMethods (ICollection methods)
105                 {
106                         foreach (MethodDefinition method in methods)
107                                 if (Annotations.IsMarked (method))
108                                         EnqueueMethod (method);
109                 }
110
111                 void Process ()
112                 {
113                         if (QueueIsEmpty ())
114                                 throw new InvalidOperationException ("No entry methods");
115
116                         while (!QueueIsEmpty ()) {
117                                 ProcessQueue ();
118                                 ProcessVirtualMethods ();
119                         }
120                 }
121
122                 void ProcessQueue ()
123                 {
124                         while (!QueueIsEmpty ()) {
125                                 MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
126                                 Annotations.Push (method);
127                                 ProcessMethod (method);
128                                 Annotations.Pop ();
129                         }
130                 }
131
132                 bool QueueIsEmpty ()
133                 {
134                         return _methods.Count == 0;
135                 }
136
137                 protected virtual void EnqueueMethod (MethodDefinition method)
138                 {
139                         _methods.Enqueue (method);
140                 }
141
142                 void ProcessVirtualMethods ()
143                 {
144                         foreach (MethodDefinition method in _virtual_methods)
145                                 ProcessVirtualMethod (method);
146                 }
147
148                 void ProcessVirtualMethod (MethodDefinition method)
149                 {
150                         IList overrides = Annotations.GetOverrides (method);
151                         if (overrides == null)
152                                 return;
153
154                         foreach (MethodDefinition @override in overrides)
155                                 ProcessOverride (@override);
156                 }
157
158                 void ProcessOverride (MethodDefinition method)
159                 {
160                         if (!Annotations.IsMarked (method.DeclaringType))
161                                 return;
162
163                         if (Annotations.IsProcessed (method))
164                                 return;
165
166                         if (Annotations.IsMarked (method))
167                                 return;
168
169                         MarkMethod (method);
170                         ProcessVirtualMethod (method);
171                 }
172
173                 void MarkMarshalSpec (IMarshalInfoProvider spec)
174                 {
175                         if (!spec.HasMarshalInfo)
176                                 return;
177
178                         var marshaler = spec.MarshalInfo as CustomMarshalInfo;
179                         if (marshaler == null)
180                                 return;
181
182                         MarkType (marshaler.ManagedType);
183                 }
184
185                 void MarkCustomAttributes (ICustomAttributeProvider provider)
186                 {
187                         if (!provider.HasCustomAttributes)
188                                 return;
189
190                         foreach (CustomAttribute ca in provider.CustomAttributes)
191                                 MarkCustomAttribute (ca);
192                 }
193
194                 protected virtual void MarkCustomAttribute (CustomAttribute ca)
195                 {
196                         MarkMethod (ca.Constructor);
197
198                         MarkCustomAttributeArguments (ca);
199
200                         TypeReference constructor_type = ca.Constructor.DeclaringType;
201                         TypeDefinition type = constructor_type.Resolve ();
202                         if (type == null)
203                                 throw new ResolutionException (constructor_type);
204
205                         MarkCustomAttributeProperties (ca, type);
206                         MarkCustomAttributeFields (ca, type);
207                 }
208
209                 protected void MarkSecurityDeclarations (ISecurityDeclarationProvider provider)
210                 {
211                         // most security declarations are removed (if linked) but user code might still have some
212                         // and if the attribtues references types then they need to be marked too
213                         if ((provider == null) || !provider.HasSecurityDeclarations)
214                                 return;
215
216                         foreach (var sd in provider.SecurityDeclarations)
217                                 MarkSecurityDeclaration (sd);
218                 }
219
220                 protected virtual void MarkSecurityDeclaration (SecurityDeclaration sd)
221                 {
222                         if (!sd.HasSecurityAttributes)
223                                 return;
224                         
225                         foreach (var sa in sd.SecurityAttributes)
226                                 MarkSecurityAttribute (sa);
227                 }
228
229                 protected virtual void MarkSecurityAttribute (SecurityAttribute sa)
230                 {
231                         TypeReference security_type = sa.AttributeType;
232                         TypeDefinition type = security_type.Resolve ();
233                         if (type == null)
234                                 throw new ResolutionException (security_type);
235                         
236                         MarkType (security_type);
237                         MarkSecurityAttributeProperties (sa, type);
238                         MarkSecurityAttributeFields (sa, type);
239                 }
240
241                 protected void MarkSecurityAttributeProperties (SecurityAttribute sa, TypeDefinition attribute)
242                 {
243                         if (!sa.HasProperties)
244                                 return;
245
246                         foreach (var named_argument in sa.Properties)
247                                 MarkCustomAttributeProperty (named_argument, attribute);
248                 }
249
250                 protected void MarkSecurityAttributeFields (SecurityAttribute sa, TypeDefinition attribute)
251                 {
252                         if (!sa.HasFields)
253                                 return;
254
255                         foreach (var named_argument in sa.Fields)
256                                 MarkCustomAttributeField (named_argument, attribute);
257                 }
258
259                 protected void MarkCustomAttributeProperties (CustomAttribute ca, TypeDefinition attribute)
260                 {
261                         if (!ca.HasProperties)
262                                 return;
263
264                         foreach (var named_argument in ca.Properties)
265                                 MarkCustomAttributeProperty (named_argument, attribute);
266                 }
267
268                 protected void MarkCustomAttributeProperty (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute)
269                 {
270                         PropertyDefinition property = GetProperty (attribute, namedArgument.Name);
271                         if (property != null)
272                                 MarkMethod (property.SetMethod);
273
274                         MarkIfType (namedArgument.Argument);
275                 }
276
277                 PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
278                 {
279                         while (type != null) {
280                                 PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname);
281                                 if (property != null)
282                                         return property;
283
284                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
285                         }
286
287                         return null;
288                 }
289
290                 protected void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition attribute)
291                 {
292                         if (!ca.HasFields)
293                                 return;
294
295                         foreach (var named_argument in ca.Fields)
296                                 MarkCustomAttributeField (named_argument, attribute);
297                 }
298
299                 protected void MarkCustomAttributeField (CustomAttributeNamedArgument namedArgument, TypeDefinition attribute)
300                 {
301                         FieldDefinition field = GetField (attribute, namedArgument.Name);
302                         if (field != null)
303                                 MarkField (field);
304
305                         MarkIfType (namedArgument.Argument);
306                 }
307
308                 FieldDefinition GetField (TypeDefinition type, string fieldname)
309                 {
310                         while (type != null) {
311                                 FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname);
312                                 if (field != null)
313                                         return field;
314
315                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
316                         }
317
318                         return null;
319                 }
320
321                 void MarkCustomAttributeArguments (CustomAttribute ca)
322                 {
323                         if (!ca.HasConstructorArguments)
324                                 return;
325
326                         foreach (var argument in ca.ConstructorArguments)
327                                 MarkIfType (argument);
328                 }
329
330                 void MarkIfType (CustomAttributeArgument argument)
331                 {
332                         var at = argument.Type;
333                         if (at.IsArray) {
334                                 var et = at.GetElementType ();
335                                 if (et.Namespace != "System" || et.Name != "Type")
336                                         return;
337
338                                 MarkType (et);
339                                 foreach (var cac in (CustomAttributeArgument[]) argument.Value)
340                                         MarkWithResolvedScope ((TypeReference) cac.Value);
341                         } else if (at.Namespace == "System" && at.Name == "Type") {
342                                 MarkType (argument.Type);
343                                 MarkWithResolvedScope ((TypeReference) argument.Value);
344                         }
345                 }
346
347                 // custom attributes encoding means it's possible to have a scope that will point into a PCL facade
348                 // even if we (just before saving) will resolve all type references (bug #26752)
349                 void MarkWithResolvedScope (TypeReference type)
350                 {
351                         if (type == null)
352                                 return;
353
354                         // a GenericInstanceType can could contains generic arguments with scope that
355                         // needs to be updated out of the PCL facade (bug #28823)
356                         var git = (type as GenericInstanceType);
357                         if ((git != null) && git.HasGenericArguments) {
358                                 foreach (var ga in git.GenericArguments)
359                                         MarkWithResolvedScope (ga);
360                         }
361                         // we cannot set the Scope of a TypeSpecification but it's element type can be set
362                         // e.g. System.String[] -> System.String
363                         var ts = (type as TypeSpecification);
364                         if (ts != null) {
365                                 MarkWithResolvedScope (ts.GetElementType ());
366                                 return;
367                         }
368
369                         var td = type.Resolve ();
370                         if (td != null)
371                                 type.Scope = td.Scope;
372                         MarkType (type);
373                 }
374
375                 protected bool CheckProcessed (IMetadataTokenProvider provider)
376                 {
377                         if (Annotations.IsProcessed (provider))
378                                 return true;
379
380                         Annotations.Processed (provider);
381                         return false;
382                 }
383
384                 protected void MarkAssembly (AssemblyDefinition assembly)
385                 {
386                         if (CheckProcessed (assembly))
387                                 return;
388
389                         ProcessModule (assembly);
390
391                         MarkCustomAttributes (assembly);
392                         MarkSecurityDeclarations (assembly);
393
394                         foreach (ModuleDefinition module in assembly.Modules)
395                                 MarkCustomAttributes (module);
396                 }
397
398                 void ProcessModule (AssemblyDefinition assembly)
399                 {
400                         // Pre-mark <Module> if there is any methods as they need to be executed 
401                         // at assembly load time
402                         foreach (TypeDefinition type in assembly.MainModule.Types)
403                         {
404                                 if (type.Name == "<Module>" && type.HasMethods)
405                                 {
406                                         MarkType (type);
407                                         break;
408                                 }
409                         }
410                 }
411
412                 protected void MarkField (FieldReference reference)
413                 {
414 //                      if (IgnoreScope (reference.DeclaringType.Scope))
415 //                              return;
416
417                         if (reference.DeclaringType is GenericInstanceType)
418                                 MarkType (reference.DeclaringType);
419
420                         FieldDefinition field = ResolveFieldDefinition (reference);
421
422                         if (field == null)
423                                 throw new ResolutionException (reference);
424
425                         if (CheckProcessed (field))
426                                 return;
427
428                         MarkType (field.DeclaringType);
429                         MarkType (field.FieldType);
430                         MarkCustomAttributes (field);
431                         MarkMarshalSpec (field);
432
433                         Annotations.Mark (field);
434                 }
435
436                 protected virtual bool IgnoreScope (IMetadataScope scope)
437                 {
438                         AssemblyDefinition assembly = ResolveAssembly (scope);
439                         return Annotations.GetAction (assembly) != AssemblyAction.Link;
440                 }
441
442                 FieldDefinition ResolveFieldDefinition (FieldReference field)
443                 {
444                         FieldDefinition fd = field as FieldDefinition;
445                         if (fd == null)
446                                 fd = field.Resolve ();
447
448                         return fd;
449                 }
450
451                 void MarkScope (IMetadataScope scope)
452                 {
453                         var provider = scope as IMetadataTokenProvider;
454                         if (provider == null)
455                                 return;
456
457                         Annotations.Mark (provider);
458                 }
459
460                 protected virtual void MarkSerializable (TypeDefinition type)
461                 {
462                         MarkDefaultConstructor (type);
463                         MarkMethodsIf (type.Methods, IsSpecialSerializationConstructorPredicate);
464                 }
465
466                 protected virtual TypeDefinition MarkType (TypeReference reference)
467                 {
468                         if (reference == null)
469                                 return null;
470
471                         reference = GetOriginalType (reference);
472
473                         if (reference is GenericParameter)
474                                 return null;
475
476 //                      if (IgnoreScope (reference.Scope))
477 //                              return;
478
479                         TypeDefinition type = ResolveTypeDefinition (reference);
480
481                         if (type == null)
482                                 throw new ResolutionException (reference);
483
484                         if (CheckProcessed (type))
485                                 return null;
486
487                         Annotations.Push (type);
488
489                         MarkScope (type.Scope);
490                         MarkType (type.BaseType);
491                         MarkType (type.DeclaringType);
492                         MarkCustomAttributes (type);
493                         MarkSecurityDeclarations (type);
494
495                         if (IsMulticastDelegate (type)) {
496                                 MarkMethodCollection (type.Methods);
497                         }
498
499                         if (IsSerializable (type))
500                                 MarkSerializable (type);
501
502                         MarkTypeSpecialCustomAttributes (type);
503
504                         MarkGenericParameterProvider (type);
505
506                         // keep fields for value-types and for classes with LayoutKind.Sequential or Explicit
507                         if (type.IsValueType || !type.IsAutoLayout)
508                                 MarkFields (type, type.IsEnum);
509
510                         if (type.HasInterfaces) {
511                                 foreach (TypeReference iface in type.Interfaces)
512                                         MarkType (iface);
513                         }
514
515                         if (type.HasMethods) {
516                                 MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
517                                 MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
518                         }
519
520                         DoAdditionalTypeProcessing (type);
521
522                         Annotations.Pop ();
523
524                         Annotations.Mark (type);
525
526                         ApplyPreserveInfo (type);
527
528                         return type;
529                 }
530
531                 // Allow subclassers to mark additional things when marking a method
532                 protected virtual void DoAdditionalTypeProcessing (TypeDefinition method)
533                 {
534                 }
535
536                 void MarkTypeSpecialCustomAttributes (TypeDefinition type)
537                 {
538                         if (!type.HasCustomAttributes)
539                                 return;
540
541                         foreach (CustomAttribute attribute in type.CustomAttributes) {
542                                 switch (attribute.Constructor.DeclaringType.FullName) {
543                                 case "System.Xml.Serialization.XmlSchemaProviderAttribute":
544                                         MarkXmlSchemaProvider (type, attribute);
545                                         break;
546                                 }
547                         }
548                 }
549
550                 void MarkMethodSpecialCustomAttributes (MethodDefinition method)
551                 {
552                         if (!method.HasCustomAttributes)
553                                 return;
554
555                         foreach (CustomAttribute attribute in method.CustomAttributes) {
556                                 switch (attribute.Constructor.DeclaringType.FullName) {
557                                 case "System.Web.Services.Protocols.SoapHeaderAttribute":
558                                         MarkSoapHeader (method, attribute);
559                                         break;
560                                 }
561                         }
562                 }
563
564                 void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
565                 {
566                         string method_name;
567                         if (!TryGetStringArgument (attribute, out method_name))
568                                 return;
569
570                         MarkNamedMethod (type, method_name);
571                 }
572
573                 static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
574                 {
575                         argument = null;
576
577                         if (attribute.ConstructorArguments.Count < 1)
578                                 return false;
579
580                         argument = attribute.ConstructorArguments [0].Value as string;
581
582                         return argument != null;
583                 }
584
585                 protected int MarkNamedMethod (TypeDefinition type, string method_name)
586                 {
587                         if (!type.HasMethods)
588                                 return 0;
589
590                         int count = 0;
591                         foreach (MethodDefinition method in type.Methods) {
592                                 if (method.Name != method_name)
593                                         continue;
594
595                                 MarkMethod (method);
596                                 count++;
597                         }
598
599                         return count;
600                 }
601
602                 void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
603                 {
604                         string member_name;
605                         if (!TryGetStringArgument (attribute, out member_name))
606                                 return;
607
608                         MarkNamedField (method.DeclaringType, member_name);
609                         MarkNamedProperty (method.DeclaringType, member_name);
610                 }
611
612                 void MarkNamedField (TypeDefinition type, string field_name)
613                 {
614                         if (!type.HasFields)
615                                 return;
616
617                         foreach (FieldDefinition field in type.Fields) {
618                                 if (field.Name != field_name)
619                                         continue;
620
621                                 MarkField (field);
622                         }
623                 }
624
625                 void MarkNamedProperty (TypeDefinition type, string property_name)
626                 {
627                         if (!type.HasProperties)
628                                 return;
629
630                         foreach (PropertyDefinition property in type.Properties) {
631                                 if (property.Name != property_name)
632                                         continue;
633
634                                 MarkMethod (property.GetMethod);
635                                 MarkMethod (property.SetMethod);
636                         }
637                 }
638
639                 void MarkGenericParameterProvider (IGenericParameterProvider provider)
640                 {
641                         if (!provider.HasGenericParameters)
642                                 return;
643
644                         foreach (GenericParameter parameter in provider.GenericParameters)
645                                 MarkGenericParameter (parameter);
646                 }
647
648                 void MarkGenericParameter (GenericParameter parameter)
649                 {
650                         MarkCustomAttributes (parameter);
651                         foreach (TypeReference constraint in parameter.Constraints)
652                                 MarkType (constraint);
653                 }
654
655                 bool IsVirtualAndHasPreservedParent (MethodDefinition method)
656                 {
657                         if (!method.IsVirtual)
658                                 return false;
659
660                         var base_list = Annotations.GetBaseMethods (method);
661                         if (base_list == null)
662                                 return false;
663
664                         foreach (MethodDefinition @base in base_list) {
665                                 if (IgnoreScope (@base.DeclaringType.Scope))
666                                         return true;
667
668                                 if (IsVirtualAndHasPreservedParent (@base))
669                                         return true;
670                         }
671
672                         return false;
673                 }
674
675                 static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
676
677                 static bool IsSpecialSerializationConstructor (MethodDefinition method)
678                 {
679                         if (!IsConstructor (method))
680                                 return false;
681
682                         var parameters = method.Parameters;
683                         if (parameters.Count != 2)
684                                 return false;
685
686                         return parameters [0].ParameterType.Name == "SerializationInfo" &&
687                                 parameters [1].ParameterType.Name == "StreamingContext";
688                 }
689
690                 delegate bool MethodPredicate (MethodDefinition method);
691
692                 void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
693                 {
694                         foreach (MethodDefinition method in methods)
695                                 if (predicate (method))
696                                         MarkMethod (method);
697                 }
698
699                 static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
700
701                 static bool IsDefaultConstructor (MethodDefinition method)
702                 {
703                         return IsConstructor (method) && !method.HasParameters;
704                 }
705
706                 static bool IsConstructor (MethodDefinition method)
707                 {
708                         return method.IsConstructor && !method.IsStatic;
709                 }
710
711                 protected void MarkDefaultConstructor (TypeDefinition type)
712                 {
713                         if ((type == null) || !type.HasMethods)
714                                 return;
715
716                         MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
717                 }
718
719                 static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
720
721                 static bool IsStaticConstructor (MethodDefinition method)
722                 {
723                         return method.IsConstructor && method.IsStatic;
724                 }
725
726                 static bool IsSerializable (TypeDefinition td)
727                 {
728                         return (td.Attributes & TypeAttributes.Serializable) != 0;
729                 }
730
731                 static bool IsMulticastDelegate (TypeDefinition td)
732                 {
733                         return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
734                 }
735
736                 protected TypeDefinition ResolveTypeDefinition (TypeReference type)
737                 {
738                         TypeDefinition td = type as TypeDefinition;
739                         if (td == null)
740                                 td = type.Resolve ();
741
742                         return td;
743                 }
744
745                 protected TypeReference GetOriginalType (TypeReference type)
746                 {
747                         while (type is TypeSpecification) {
748                                 GenericInstanceType git = type as GenericInstanceType;
749                                 if (git != null)
750                                         MarkGenericArguments (git);
751
752                                 var mod = type as IModifierType;
753                                 if (mod != null)
754                                         MarkModifierType (mod);
755
756                                 type = ((TypeSpecification) type).ElementType;
757                         }
758
759                         return type;
760                 }
761
762                 void MarkModifierType (IModifierType mod)
763                 {
764                         MarkType (mod.ModifierType);
765                 }
766
767                 void MarkGenericArguments (IGenericInstance instance)
768                 {
769                         foreach (TypeReference argument in instance.GenericArguments)
770                                 MarkType (argument);
771
772                         MarkGenericArgumentConstructors (instance);
773                 }
774
775                 void MarkGenericArgumentConstructors (IGenericInstance instance)
776                 {
777                         var arguments = instance.GenericArguments;
778
779                         var generic_element = GetGenericProviderFromInstance (instance);
780                         if (generic_element == null)
781                                 return;
782
783                         var parameters = generic_element.GenericParameters;
784
785                         if (arguments.Count != parameters.Count)
786                                 return;
787
788                         for (int i = 0; i < arguments.Count; i++) {
789                                 var argument = arguments [i];
790                                 var parameter = parameters [i];
791
792                                 if (!parameter.HasDefaultConstructorConstraint)
793                                         continue;
794
795                                 var argument_definition = ResolveTypeDefinition (argument);
796                                 if (argument_definition == null)
797                                         continue;
798
799                                 MarkMethodsIf (argument_definition.Methods, ctor => !ctor.IsStatic && !ctor.HasParameters);
800                         }
801                 }
802
803                 IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
804                 {
805                         var method = instance as GenericInstanceMethod;
806                         if (method != null)
807                                 return ResolveMethodDefinition (method.ElementMethod);
808
809                         var type = instance as GenericInstanceType;
810                         if (type != null)
811                                 return ResolveTypeDefinition (type.ElementType);
812
813                         return null;
814                 }
815
816                 void ApplyPreserveInfo (TypeDefinition type)
817                 {
818                         ApplyPreserveMethods (type);
819
820                         if (!Annotations.IsPreserved (type))
821                                 return;
822
823                         switch (Annotations.GetPreserve (type)) {
824                         case TypePreserve.All:
825                                 MarkFields (type, true);
826                                 MarkMethods (type);
827                                 break;
828                         case TypePreserve.Fields:
829                                 MarkFields (type, true);
830                                 break;
831                         case TypePreserve.Methods:
832                                 MarkMethods (type);
833                                 break;
834                         }
835                 }
836
837                 void ApplyPreserveMethods (TypeDefinition type)
838                 {
839                         var list = Annotations.GetPreservedMethods (type);
840                         if (list == null)
841                                 return;
842
843                         MarkMethodCollection (list);
844                 }
845
846                 void ApplyPreserveMethods (MethodDefinition method)
847                 {
848                         var list = Annotations.GetPreservedMethods (method);
849                         if (list == null)
850                                 return;
851
852                         MarkMethodCollection (list);
853                 }
854
855                 protected void MarkFields (TypeDefinition type, bool includeStatic)
856                 {
857                         if (!type.HasFields)
858                                 return;
859
860                         foreach (FieldDefinition field in type.Fields) {
861                                 if (!includeStatic && field.IsStatic)
862                                         continue;
863                                 MarkField (field);
864                         }
865                 }
866
867                 protected virtual void MarkMethods (TypeDefinition type)
868                 {
869                         if (type.HasMethods)
870                                 MarkMethodCollection (type.Methods);
871                 }
872
873                 void MarkMethodCollection (IEnumerable methods)
874                 {
875                         foreach (MethodDefinition method in methods)
876                                 MarkMethod (method);
877                 }
878
879                 protected virtual MethodDefinition MarkMethod (MethodReference reference)
880                 {
881                         reference = GetOriginalMethod (reference);
882
883                         if (reference.DeclaringType is ArrayType)
884                                 return null;
885
886                         Annotations.Push (reference);
887                         if (reference.DeclaringType is GenericInstanceType)
888                                 MarkType (reference.DeclaringType);
889
890 //                      if (IgnoreScope (reference.DeclaringType.Scope))
891 //                              return;
892
893                         MethodDefinition method = ResolveMethodDefinition (reference);
894
895                         if (method == null) {
896                                 Annotations.Pop ();
897                                 throw new ResolutionException (reference);
898                         }
899
900                         if (Annotations.GetAction (method) == MethodAction.Nothing)
901                                 Annotations.SetAction (method, MethodAction.Parse);
902
903                         EnqueueMethod (method);
904
905                         Annotations.Pop ();
906
907                         return method;
908                 }
909
910                 AssemblyDefinition ResolveAssembly (IMetadataScope scope)
911                 {
912                         AssemblyDefinition assembly = _context.Resolve (scope);
913                         MarkAssembly (assembly);
914                         return assembly;
915                 }
916
917                 protected MethodReference GetOriginalMethod (MethodReference method)
918                 {
919                         while (method is MethodSpecification) {
920                                 GenericInstanceMethod gim = method as GenericInstanceMethod;
921                                 if (gim != null)
922                                         MarkGenericArguments (gim);
923
924                                 method = ((MethodSpecification) method).ElementMethod;
925                         }
926
927                         return method;
928                 }
929
930                 MethodDefinition ResolveMethodDefinition (MethodReference method)
931                 {
932                         MethodDefinition md = method as MethodDefinition;
933                         if (md == null)
934                                 md = method.Resolve ();
935
936                         return md;
937                 }
938
939                 protected virtual void ProcessMethod (MethodDefinition method)
940                 {
941                         if (CheckProcessed (method))
942                                 return;
943
944                         MarkType (method.DeclaringType);
945                         MarkCustomAttributes (method);
946                         MarkSecurityDeclarations (method);
947
948                         MarkGenericParameterProvider (method);
949
950                         if (IsPropertyMethod (method))
951                                 MarkProperty (GetProperty (method));
952                         else if (IsEventMethod (method))
953                                 MarkEvent (GetEvent (method));
954
955                         if (method.HasParameters) {
956                                 foreach (ParameterDefinition pd in method.Parameters) {
957                                         MarkType (pd.ParameterType);
958                                         MarkCustomAttributes (pd);
959                                         MarkMarshalSpec (pd);
960                                 }
961                         }
962
963                         if (method.HasOverrides) {
964                                 foreach (MethodReference ov in method.Overrides)
965                                         MarkMethod (ov);
966                         }
967
968                         MarkMethodSpecialCustomAttributes (method);
969
970                         if (method.IsVirtual)
971                                 _virtual_methods.Add (method);
972
973                         MarkBaseMethods (method);
974
975                         MarkType (method.ReturnType);
976                         MarkCustomAttributes (method.MethodReturnType);
977                         MarkMarshalSpec (method.MethodReturnType);
978
979                         if (ShouldParseMethodBody (method))
980                                 MarkMethodBody (method.Body);
981
982                         DoAdditionalMethodProcessing (method);
983
984                         Annotations.Mark (method);
985
986                         ApplyPreserveMethods (method);
987                 }
988
989                 // Allow subclassers to mark additional things when marking a method
990                 protected virtual void DoAdditionalMethodProcessing (MethodDefinition method)
991                 {
992                 }
993
994                 void MarkBaseMethods (MethodDefinition method)
995                 {
996                         IList base_methods = Annotations.GetBaseMethods (method);
997                         if (base_methods == null)
998                                 return;
999
1000                         foreach (MethodDefinition base_method in base_methods) {
1001                                 if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface)
1002                                         continue;
1003
1004                                 MarkMethod (base_method);
1005                                 MarkBaseMethods (base_method);
1006                         }
1007                 }
1008
1009                 bool ShouldParseMethodBody (MethodDefinition method)
1010                 {
1011                         if (!method.HasBody)
1012                                 return false;
1013
1014                         AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope);
1015                         return (Annotations.GetAction (method) == MethodAction.ForceParse ||
1016                                 (Annotations.GetAction (assembly) == AssemblyAction.Link && Annotations.GetAction (method) == MethodAction.Parse));
1017                 }
1018
1019                 static internal bool IsPropertyMethod (MethodDefinition md)
1020                 {
1021                         return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 ||
1022                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
1023                 }
1024
1025                 static bool IsEventMethod (MethodDefinition md)
1026                 {
1027                         return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
1028                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 ||
1029                                 (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
1030                 }
1031
1032                 static internal PropertyDefinition GetProperty (MethodDefinition md)
1033                 {
1034                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
1035                         foreach (PropertyDefinition prop in declaringType.Properties)
1036                                 if (prop.GetMethod == md || prop.SetMethod == md)
1037                                         return prop;
1038
1039                         return null;
1040                 }
1041
1042                 static EventDefinition GetEvent (MethodDefinition md)
1043                 {
1044                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
1045                         foreach (EventDefinition evt in declaringType.Events)
1046                                 if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md)
1047                                         return evt;
1048
1049                         return null;
1050                 }
1051
1052                 protected void MarkProperty (PropertyDefinition prop)
1053                 {
1054                         MarkCustomAttributes (prop);
1055                 }
1056
1057                 protected void MarkEvent (EventDefinition evt)
1058                 {
1059                         MarkCustomAttributes (evt);
1060                         MarkMethodIfNotNull (evt.AddMethod);
1061                         MarkMethodIfNotNull (evt.InvokeMethod);
1062                         MarkMethodIfNotNull (evt.RemoveMethod);
1063                 }
1064
1065                 void MarkMethodIfNotNull (MethodReference method)
1066                 {
1067                         if (method == null)
1068                                 return;
1069
1070                         MarkMethod (method);
1071                 }
1072
1073                 protected virtual void MarkMethodBody (MethodBody body)
1074                 {
1075                         foreach (VariableDefinition var in body.Variables)
1076                                 MarkType (var.VariableType);
1077
1078                         foreach (ExceptionHandler eh in body.ExceptionHandlers)
1079                                 if (eh.HandlerType == ExceptionHandlerType.Catch)
1080                                         MarkType (eh.CatchType);
1081
1082                         foreach (Instruction instruction in body.Instructions)
1083                                 MarkInstruction (instruction);
1084                 }
1085
1086                 protected virtual void MarkInstruction (Instruction instruction)
1087                 {
1088                         switch (instruction.OpCode.OperandType) {
1089                         case OperandType.InlineField:
1090                                 MarkField ((FieldReference) instruction.Operand);
1091                                 break;
1092                         case OperandType.InlineMethod:
1093                                 MarkMethod ((MethodReference) instruction.Operand);
1094                                 break;
1095                         case OperandType.InlineTok:
1096                                 object token = instruction.Operand;
1097                                 if (token is TypeReference)
1098                                         MarkType ((TypeReference) token);
1099                                 else if (token is MethodReference)
1100                                         MarkMethod ((MethodReference) token);
1101                                 else
1102                                         MarkField ((FieldReference) token);
1103                                 break;
1104                         case OperandType.InlineType:
1105                                 MarkType ((TypeReference) instruction.Operand);
1106                                 break;
1107                         default:
1108                                 break;
1109                         }
1110                 }
1111         }
1112 }