Merge pull request #2353 from ludovic-henry/fix-servicemodel-15153
[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                                 if (argument.Value == null)
340                                         return;
341
342                                 foreach (var cac in (CustomAttributeArgument[]) argument.Value)
343                                         MarkWithResolvedScope ((TypeReference) cac.Value);
344                         } else if (at.Namespace == "System" && at.Name == "Type") {
345                                 MarkType (argument.Type);
346                                 MarkWithResolvedScope ((TypeReference) argument.Value);
347                         }
348                 }
349
350                 // custom attributes encoding means it's possible to have a scope that will point into a PCL facade
351                 // even if we (just before saving) will resolve all type references (bug #26752)
352                 void MarkWithResolvedScope (TypeReference type)
353                 {
354                         if (type == null)
355                                 return;
356
357                         // a GenericInstanceType can could contains generic arguments with scope that
358                         // needs to be updated out of the PCL facade (bug #28823)
359                         var git = (type as GenericInstanceType);
360                         if ((git != null) && git.HasGenericArguments) {
361                                 foreach (var ga in git.GenericArguments)
362                                         MarkWithResolvedScope (ga);
363                         }
364                         // we cannot set the Scope of a TypeSpecification but it's element type can be set
365                         // e.g. System.String[] -> System.String
366                         var ts = (type as TypeSpecification);
367                         if (ts != null) {
368                                 MarkWithResolvedScope (ts.GetElementType ());
369                                 return;
370                         }
371
372                         var td = type.Resolve ();
373                         if (td != null)
374                                 type.Scope = td.Scope;
375                         MarkType (type);
376                 }
377
378                 protected bool CheckProcessed (IMetadataTokenProvider provider)
379                 {
380                         if (Annotations.IsProcessed (provider))
381                                 return true;
382
383                         Annotations.Processed (provider);
384                         return false;
385                 }
386
387                 protected void MarkAssembly (AssemblyDefinition assembly)
388                 {
389                         if (CheckProcessed (assembly))
390                                 return;
391
392                         ProcessModule (assembly);
393
394                         MarkCustomAttributes (assembly);
395                         MarkSecurityDeclarations (assembly);
396
397                         foreach (ModuleDefinition module in assembly.Modules)
398                                 MarkCustomAttributes (module);
399                 }
400
401                 void ProcessModule (AssemblyDefinition assembly)
402                 {
403                         // Pre-mark <Module> if there is any methods as they need to be executed 
404                         // at assembly load time
405                         foreach (TypeDefinition type in assembly.MainModule.Types)
406                         {
407                                 if (type.Name == "<Module>" && type.HasMethods)
408                                 {
409                                         MarkType (type);
410                                         break;
411                                 }
412                         }
413                 }
414
415                 protected void MarkField (FieldReference reference)
416                 {
417 //                      if (IgnoreScope (reference.DeclaringType.Scope))
418 //                              return;
419
420                         if (reference.DeclaringType is GenericInstanceType)
421                                 MarkType (reference.DeclaringType);
422
423                         FieldDefinition field = ResolveFieldDefinition (reference);
424
425                         if (field == null)
426                                 throw new ResolutionException (reference);
427
428                         if (CheckProcessed (field))
429                                 return;
430
431                         MarkType (field.DeclaringType);
432                         MarkType (field.FieldType);
433                         MarkCustomAttributes (field);
434                         MarkMarshalSpec (field);
435
436                         Annotations.Mark (field);
437                 }
438
439                 protected virtual bool IgnoreScope (IMetadataScope scope)
440                 {
441                         AssemblyDefinition assembly = ResolveAssembly (scope);
442                         return Annotations.GetAction (assembly) != AssemblyAction.Link;
443                 }
444
445                 FieldDefinition ResolveFieldDefinition (FieldReference field)
446                 {
447                         FieldDefinition fd = field as FieldDefinition;
448                         if (fd == null)
449                                 fd = field.Resolve ();
450
451                         return fd;
452                 }
453
454                 void MarkScope (IMetadataScope scope)
455                 {
456                         var provider = scope as IMetadataTokenProvider;
457                         if (provider == null)
458                                 return;
459
460                         Annotations.Mark (provider);
461                 }
462
463                 protected virtual void MarkSerializable (TypeDefinition type)
464                 {
465                         MarkDefaultConstructor (type);
466                         MarkMethodsIf (type.Methods, IsSpecialSerializationConstructorPredicate);
467                 }
468
469                 protected virtual TypeDefinition MarkType (TypeReference reference)
470                 {
471                         if (reference == null)
472                                 return null;
473
474                         reference = GetOriginalType (reference);
475
476                         if (reference is GenericParameter)
477                                 return null;
478
479 //                      if (IgnoreScope (reference.Scope))
480 //                              return;
481
482                         TypeDefinition type = ResolveTypeDefinition (reference);
483
484                         if (type == null)
485                                 throw new ResolutionException (reference);
486
487                         if (CheckProcessed (type))
488                                 return null;
489
490                         Annotations.Push (type);
491
492                         MarkScope (type.Scope);
493                         MarkType (type.BaseType);
494                         MarkType (type.DeclaringType);
495                         MarkCustomAttributes (type);
496                         MarkSecurityDeclarations (type);
497
498                         if (IsMulticastDelegate (type)) {
499                                 MarkMethodCollection (type.Methods);
500                         }
501
502                         if (IsSerializable (type))
503                                 MarkSerializable (type);
504
505                         MarkTypeSpecialCustomAttributes (type);
506
507                         MarkGenericParameterProvider (type);
508
509                         // keep fields for value-types and for classes with LayoutKind.Sequential or Explicit
510                         if (type.IsValueType || !type.IsAutoLayout)
511                                 MarkFields (type, type.IsEnum);
512
513                         if (type.HasInterfaces) {
514                                 foreach (TypeReference iface in type.Interfaces)
515                                         MarkType (iface);
516                         }
517
518                         if (type.HasMethods) {
519                                 MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
520                                 MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
521                         }
522
523                         DoAdditionalTypeProcessing (type);
524
525                         Annotations.Pop ();
526
527                         Annotations.Mark (type);
528
529                         ApplyPreserveInfo (type);
530
531                         return type;
532                 }
533
534                 // Allow subclassers to mark additional things when marking a method
535                 protected virtual void DoAdditionalTypeProcessing (TypeDefinition method)
536                 {
537                 }
538
539                 void MarkTypeSpecialCustomAttributes (TypeDefinition type)
540                 {
541                         if (!type.HasCustomAttributes)
542                                 return;
543
544                         foreach (CustomAttribute attribute in type.CustomAttributes) {
545                                 switch (attribute.Constructor.DeclaringType.FullName) {
546                                 case "System.Xml.Serialization.XmlSchemaProviderAttribute":
547                                         MarkXmlSchemaProvider (type, attribute);
548                                         break;
549                                 }
550                         }
551                 }
552
553                 void MarkMethodSpecialCustomAttributes (MethodDefinition method)
554                 {
555                         if (!method.HasCustomAttributes)
556                                 return;
557
558                         foreach (CustomAttribute attribute in method.CustomAttributes) {
559                                 switch (attribute.Constructor.DeclaringType.FullName) {
560                                 case "System.Web.Services.Protocols.SoapHeaderAttribute":
561                                         MarkSoapHeader (method, attribute);
562                                         break;
563                                 }
564                         }
565                 }
566
567                 void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
568                 {
569                         string method_name;
570                         if (!TryGetStringArgument (attribute, out method_name))
571                                 return;
572
573                         MarkNamedMethod (type, method_name);
574                 }
575
576                 static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
577                 {
578                         argument = null;
579
580                         if (attribute.ConstructorArguments.Count < 1)
581                                 return false;
582
583                         argument = attribute.ConstructorArguments [0].Value as string;
584
585                         return argument != null;
586                 }
587
588                 protected int MarkNamedMethod (TypeDefinition type, string method_name)
589                 {
590                         if (!type.HasMethods)
591                                 return 0;
592
593                         int count = 0;
594                         foreach (MethodDefinition method in type.Methods) {
595                                 if (method.Name != method_name)
596                                         continue;
597
598                                 MarkMethod (method);
599                                 count++;
600                         }
601
602                         return count;
603                 }
604
605                 void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
606                 {
607                         string member_name;
608                         if (!TryGetStringArgument (attribute, out member_name))
609                                 return;
610
611                         MarkNamedField (method.DeclaringType, member_name);
612                         MarkNamedProperty (method.DeclaringType, member_name);
613                 }
614
615                 void MarkNamedField (TypeDefinition type, string field_name)
616                 {
617                         if (!type.HasFields)
618                                 return;
619
620                         foreach (FieldDefinition field in type.Fields) {
621                                 if (field.Name != field_name)
622                                         continue;
623
624                                 MarkField (field);
625                         }
626                 }
627
628                 void MarkNamedProperty (TypeDefinition type, string property_name)
629                 {
630                         if (!type.HasProperties)
631                                 return;
632
633                         foreach (PropertyDefinition property in type.Properties) {
634                                 if (property.Name != property_name)
635                                         continue;
636
637                                 MarkMethod (property.GetMethod);
638                                 MarkMethod (property.SetMethod);
639                         }
640                 }
641
642                 void MarkGenericParameterProvider (IGenericParameterProvider provider)
643                 {
644                         if (!provider.HasGenericParameters)
645                                 return;
646
647                         foreach (GenericParameter parameter in provider.GenericParameters)
648                                 MarkGenericParameter (parameter);
649                 }
650
651                 void MarkGenericParameter (GenericParameter parameter)
652                 {
653                         MarkCustomAttributes (parameter);
654                         foreach (TypeReference constraint in parameter.Constraints)
655                                 MarkType (constraint);
656                 }
657
658                 bool IsVirtualAndHasPreservedParent (MethodDefinition method)
659                 {
660                         if (!method.IsVirtual)
661                                 return false;
662
663                         var base_list = Annotations.GetBaseMethods (method);
664                         if (base_list == null)
665                                 return false;
666
667                         foreach (MethodDefinition @base in base_list) {
668                                 if (IgnoreScope (@base.DeclaringType.Scope))
669                                         return true;
670
671                                 if (IsVirtualAndHasPreservedParent (@base))
672                                         return true;
673                         }
674
675                         return false;
676                 }
677
678                 static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
679
680                 static bool IsSpecialSerializationConstructor (MethodDefinition method)
681                 {
682                         if (!IsConstructor (method))
683                                 return false;
684
685                         var parameters = method.Parameters;
686                         if (parameters.Count != 2)
687                                 return false;
688
689                         return parameters [0].ParameterType.Name == "SerializationInfo" &&
690                                 parameters [1].ParameterType.Name == "StreamingContext";
691                 }
692
693                 delegate bool MethodPredicate (MethodDefinition method);
694
695                 void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
696                 {
697                         foreach (MethodDefinition method in methods)
698                                 if (predicate (method))
699                                         MarkMethod (method);
700                 }
701
702                 static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
703
704                 static bool IsDefaultConstructor (MethodDefinition method)
705                 {
706                         return IsConstructor (method) && !method.HasParameters;
707                 }
708
709                 static bool IsConstructor (MethodDefinition method)
710                 {
711                         return method.IsConstructor && !method.IsStatic;
712                 }
713
714                 protected void MarkDefaultConstructor (TypeDefinition type)
715                 {
716                         if ((type == null) || !type.HasMethods)
717                                 return;
718
719                         MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
720                 }
721
722                 static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
723
724                 static bool IsStaticConstructor (MethodDefinition method)
725                 {
726                         return method.IsConstructor && method.IsStatic;
727                 }
728
729                 static bool IsSerializable (TypeDefinition td)
730                 {
731                         return (td.Attributes & TypeAttributes.Serializable) != 0;
732                 }
733
734                 static bool IsMulticastDelegate (TypeDefinition td)
735                 {
736                         return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
737                 }
738
739                 protected TypeDefinition ResolveTypeDefinition (TypeReference type)
740                 {
741                         TypeDefinition td = type as TypeDefinition;
742                         if (td == null)
743                                 td = type.Resolve ();
744
745                         return td;
746                 }
747
748                 protected TypeReference GetOriginalType (TypeReference type)
749                 {
750                         while (type is TypeSpecification) {
751                                 GenericInstanceType git = type as GenericInstanceType;
752                                 if (git != null)
753                                         MarkGenericArguments (git);
754
755                                 var mod = type as IModifierType;
756                                 if (mod != null)
757                                         MarkModifierType (mod);
758
759                                 type = ((TypeSpecification) type).ElementType;
760                         }
761
762                         return type;
763                 }
764
765                 void MarkModifierType (IModifierType mod)
766                 {
767                         MarkType (mod.ModifierType);
768                 }
769
770                 void MarkGenericArguments (IGenericInstance instance)
771                 {
772                         foreach (TypeReference argument in instance.GenericArguments)
773                                 MarkType (argument);
774
775                         MarkGenericArgumentConstructors (instance);
776                 }
777
778                 void MarkGenericArgumentConstructors (IGenericInstance instance)
779                 {
780                         var arguments = instance.GenericArguments;
781
782                         var generic_element = GetGenericProviderFromInstance (instance);
783                         if (generic_element == null)
784                                 return;
785
786                         var parameters = generic_element.GenericParameters;
787
788                         if (arguments.Count != parameters.Count)
789                                 return;
790
791                         for (int i = 0; i < arguments.Count; i++) {
792                                 var argument = arguments [i];
793                                 var parameter = parameters [i];
794
795                                 if (!parameter.HasDefaultConstructorConstraint)
796                                         continue;
797
798                                 var argument_definition = ResolveTypeDefinition (argument);
799                                 if (argument_definition == null)
800                                         continue;
801
802                                 MarkMethodsIf (argument_definition.Methods, ctor => !ctor.IsStatic && !ctor.HasParameters);
803                         }
804                 }
805
806                 IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
807                 {
808                         var method = instance as GenericInstanceMethod;
809                         if (method != null)
810                                 return ResolveMethodDefinition (method.ElementMethod);
811
812                         var type = instance as GenericInstanceType;
813                         if (type != null)
814                                 return ResolveTypeDefinition (type.ElementType);
815
816                         return null;
817                 }
818
819                 void ApplyPreserveInfo (TypeDefinition type)
820                 {
821                         ApplyPreserveMethods (type);
822
823                         if (!Annotations.IsPreserved (type))
824                                 return;
825
826                         switch (Annotations.GetPreserve (type)) {
827                         case TypePreserve.All:
828                                 MarkFields (type, true);
829                                 MarkMethods (type);
830                                 break;
831                         case TypePreserve.Fields:
832                                 MarkFields (type, true);
833                                 break;
834                         case TypePreserve.Methods:
835                                 MarkMethods (type);
836                                 break;
837                         }
838                 }
839
840                 void ApplyPreserveMethods (TypeDefinition type)
841                 {
842                         var list = Annotations.GetPreservedMethods (type);
843                         if (list == null)
844                                 return;
845
846                         MarkMethodCollection (list);
847                 }
848
849                 void ApplyPreserveMethods (MethodDefinition method)
850                 {
851                         var list = Annotations.GetPreservedMethods (method);
852                         if (list == null)
853                                 return;
854
855                         MarkMethodCollection (list);
856                 }
857
858                 protected void MarkFields (TypeDefinition type, bool includeStatic)
859                 {
860                         if (!type.HasFields)
861                                 return;
862
863                         foreach (FieldDefinition field in type.Fields) {
864                                 if (!includeStatic && field.IsStatic)
865                                         continue;
866                                 MarkField (field);
867                         }
868                 }
869
870                 protected virtual void MarkMethods (TypeDefinition type)
871                 {
872                         if (type.HasMethods)
873                                 MarkMethodCollection (type.Methods);
874                 }
875
876                 void MarkMethodCollection (IEnumerable methods)
877                 {
878                         foreach (MethodDefinition method in methods)
879                                 MarkMethod (method);
880                 }
881
882                 protected virtual MethodDefinition MarkMethod (MethodReference reference)
883                 {
884                         reference = GetOriginalMethod (reference);
885
886                         if (reference.DeclaringType is ArrayType)
887                                 return null;
888
889                         Annotations.Push (reference);
890                         if (reference.DeclaringType is GenericInstanceType)
891                                 MarkType (reference.DeclaringType);
892
893 //                      if (IgnoreScope (reference.DeclaringType.Scope))
894 //                              return;
895
896                         MethodDefinition method = ResolveMethodDefinition (reference);
897
898                         if (method == null) {
899                                 Annotations.Pop ();
900                                 throw new ResolutionException (reference);
901                         }
902
903                         if (Annotations.GetAction (method) == MethodAction.Nothing)
904                                 Annotations.SetAction (method, MethodAction.Parse);
905
906                         EnqueueMethod (method);
907
908                         Annotations.Pop ();
909
910                         return method;
911                 }
912
913                 AssemblyDefinition ResolveAssembly (IMetadataScope scope)
914                 {
915                         AssemblyDefinition assembly = _context.Resolve (scope);
916                         MarkAssembly (assembly);
917                         return assembly;
918                 }
919
920                 protected MethodReference GetOriginalMethod (MethodReference method)
921                 {
922                         while (method is MethodSpecification) {
923                                 GenericInstanceMethod gim = method as GenericInstanceMethod;
924                                 if (gim != null)
925                                         MarkGenericArguments (gim);
926
927                                 method = ((MethodSpecification) method).ElementMethod;
928                         }
929
930                         return method;
931                 }
932
933                 MethodDefinition ResolveMethodDefinition (MethodReference method)
934                 {
935                         MethodDefinition md = method as MethodDefinition;
936                         if (md == null)
937                                 md = method.Resolve ();
938
939                         return md;
940                 }
941
942                 protected virtual void ProcessMethod (MethodDefinition method)
943                 {
944                         if (CheckProcessed (method))
945                                 return;
946
947                         MarkType (method.DeclaringType);
948                         MarkCustomAttributes (method);
949                         MarkSecurityDeclarations (method);
950
951                         MarkGenericParameterProvider (method);
952
953                         if (IsPropertyMethod (method))
954                                 MarkProperty (GetProperty (method));
955                         else if (IsEventMethod (method))
956                                 MarkEvent (GetEvent (method));
957
958                         if (method.HasParameters) {
959                                 foreach (ParameterDefinition pd in method.Parameters) {
960                                         MarkType (pd.ParameterType);
961                                         MarkCustomAttributes (pd);
962                                         MarkMarshalSpec (pd);
963                                 }
964                         }
965
966                         if (method.HasOverrides) {
967                                 foreach (MethodReference ov in method.Overrides)
968                                         MarkMethod (ov);
969                         }
970
971                         MarkMethodSpecialCustomAttributes (method);
972
973                         if (method.IsVirtual)
974                                 _virtual_methods.Add (method);
975
976                         MarkBaseMethods (method);
977
978                         MarkType (method.ReturnType);
979                         MarkCustomAttributes (method.MethodReturnType);
980                         MarkMarshalSpec (method.MethodReturnType);
981
982                         if (ShouldParseMethodBody (method))
983                                 MarkMethodBody (method.Body);
984
985                         DoAdditionalMethodProcessing (method);
986
987                         Annotations.Mark (method);
988
989                         ApplyPreserveMethods (method);
990                 }
991
992                 // Allow subclassers to mark additional things when marking a method
993                 protected virtual void DoAdditionalMethodProcessing (MethodDefinition method)
994                 {
995                 }
996
997                 void MarkBaseMethods (MethodDefinition method)
998                 {
999                         IList base_methods = Annotations.GetBaseMethods (method);
1000                         if (base_methods == null)
1001                                 return;
1002
1003                         foreach (MethodDefinition base_method in base_methods) {
1004                                 if (base_method.DeclaringType.IsInterface && !method.DeclaringType.IsInterface)
1005                                         continue;
1006
1007                                 MarkMethod (base_method);
1008                                 MarkBaseMethods (base_method);
1009                         }
1010                 }
1011
1012                 bool ShouldParseMethodBody (MethodDefinition method)
1013                 {
1014                         if (!method.HasBody)
1015                                 return false;
1016
1017                         AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope);
1018                         return (Annotations.GetAction (method) == MethodAction.ForceParse ||
1019                                 (Annotations.GetAction (assembly) == AssemblyAction.Link && Annotations.GetAction (method) == MethodAction.Parse));
1020                 }
1021
1022                 static internal bool IsPropertyMethod (MethodDefinition md)
1023                 {
1024                         return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 ||
1025                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
1026                 }
1027
1028                 static bool IsEventMethod (MethodDefinition md)
1029                 {
1030                         return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
1031                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 ||
1032                                 (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
1033                 }
1034
1035                 static internal PropertyDefinition GetProperty (MethodDefinition md)
1036                 {
1037                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
1038                         foreach (PropertyDefinition prop in declaringType.Properties)
1039                                 if (prop.GetMethod == md || prop.SetMethod == md)
1040                                         return prop;
1041
1042                         return null;
1043                 }
1044
1045                 static EventDefinition GetEvent (MethodDefinition md)
1046                 {
1047                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
1048                         foreach (EventDefinition evt in declaringType.Events)
1049                                 if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md)
1050                                         return evt;
1051
1052                         return null;
1053                 }
1054
1055                 protected void MarkProperty (PropertyDefinition prop)
1056                 {
1057                         MarkCustomAttributes (prop);
1058                 }
1059
1060                 protected void MarkEvent (EventDefinition evt)
1061                 {
1062                         MarkCustomAttributes (evt);
1063                         MarkMethodIfNotNull (evt.AddMethod);
1064                         MarkMethodIfNotNull (evt.InvokeMethod);
1065                         MarkMethodIfNotNull (evt.RemoveMethod);
1066                 }
1067
1068                 void MarkMethodIfNotNull (MethodReference method)
1069                 {
1070                         if (method == null)
1071                                 return;
1072
1073                         MarkMethod (method);
1074                 }
1075
1076                 protected virtual void MarkMethodBody (MethodBody body)
1077                 {
1078                         foreach (VariableDefinition var in body.Variables)
1079                                 MarkType (var.VariableType);
1080
1081                         foreach (ExceptionHandler eh in body.ExceptionHandlers)
1082                                 if (eh.HandlerType == ExceptionHandlerType.Catch)
1083                                         MarkType (eh.CatchType);
1084
1085                         foreach (Instruction instruction in body.Instructions)
1086                                 MarkInstruction (instruction);
1087                 }
1088
1089                 protected virtual void MarkInstruction (Instruction instruction)
1090                 {
1091                         switch (instruction.OpCode.OperandType) {
1092                         case OperandType.InlineField:
1093                                 MarkField ((FieldReference) instruction.Operand);
1094                                 break;
1095                         case OperandType.InlineMethod:
1096                                 MarkMethod ((MethodReference) instruction.Operand);
1097                                 break;
1098                         case OperandType.InlineTok:
1099                                 object token = instruction.Operand;
1100                                 if (token is TypeReference)
1101                                         MarkType ((TypeReference) token);
1102                                 else if (token is MethodReference)
1103                                         MarkMethod ((MethodReference) token);
1104                                 else
1105                                         MarkField ((FieldReference) token);
1106                                 break;
1107                         case OperandType.InlineType:
1108                                 MarkType ((TypeReference) instruction.Operand);
1109                                 break;
1110                         default:
1111                                 break;
1112                         }
1113                 }
1114         }
1115 }