Update mcs/class/System.Core/System/TimeZoneInfo.cs
[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                                         InitializeType (nested);
92                 }
93
94                 void InitializeFields (TypeDefinition type)
95                 {
96                         foreach (FieldDefinition field in type.Fields)
97                                 if (Annotations.IsMarked (field))
98                                         MarkField (field);
99                 }
100
101                 void InitializeMethods (ICollection methods)
102                 {
103                         foreach (MethodDefinition method in methods)
104                                 if (Annotations.IsMarked (method))
105                                         EnqueueMethod (method);
106                 }
107
108                 void Process ()
109                 {
110                         if (QueueIsEmpty ())
111                                 throw new InvalidOperationException ("No entry methods");
112
113                         while (!QueueIsEmpty ()) {
114                                 ProcessQueue ();
115                                 ProcessVirtualMethods ();
116                         }
117                 }
118
119                 void ProcessQueue ()
120                 {
121                         while (!QueueIsEmpty ()) {
122                                 MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
123                                 ProcessMethod (method);
124                         }
125                 }
126
127                 bool QueueIsEmpty ()
128                 {
129                         return _methods.Count == 0;
130                 }
131
132                 protected virtual void EnqueueMethod (MethodDefinition method)
133                 {
134                         _methods.Enqueue (method);
135                 }
136
137                 void ProcessVirtualMethods ()
138                 {
139                         foreach (MethodDefinition method in _virtual_methods)
140                                 ProcessVirtualMethod (method);
141                 }
142
143                 void ProcessVirtualMethod (MethodDefinition method)
144                 {
145                         IList overrides = Annotations.GetOverrides (method);
146                         if (overrides == null)
147                                 return;
148
149                         foreach (MethodDefinition @override in overrides)
150                                 ProcessOverride (@override);
151                 }
152
153                 void ProcessOverride (MethodDefinition method)
154                 {
155                         if (!Annotations.IsMarked (method.DeclaringType))
156                                 return;
157
158                         if (Annotations.IsProcessed (method))
159                                 return;
160
161                         if (Annotations.IsMarked (method))
162                                 return;
163
164                         MarkMethod (method);
165                         ProcessVirtualMethod (method);
166                 }
167
168                 void MarkMarshalSpec (IMarshalInfoProvider spec)
169                 {
170                         if (!spec.HasMarshalInfo)
171                                 return;
172
173                         var marshaler = spec.MarshalInfo as CustomMarshalInfo;
174                         if (marshaler == null)
175                                 return;
176
177                         MarkType (marshaler.ManagedType);
178                 }
179
180                 void MarkCustomAttributes (ICustomAttributeProvider provider)
181                 {
182                         if (!provider.HasCustomAttributes)
183                                 return;
184
185                         foreach (CustomAttribute ca in provider.CustomAttributes)
186                                 MarkCustomAttribute (ca);
187                 }
188
189                 void MarkCustomAttribute (CustomAttribute ca)
190                 {
191                         MarkMethod (ca.Constructor);
192
193                         MarkCustomAttributeArguments (ca);
194
195                         TypeReference constructor_type = ca.Constructor.DeclaringType;
196                         TypeDefinition type = constructor_type.Resolve ();
197                         if (type == null)
198                                 throw new ResolutionException (constructor_type);
199
200                         MarkCustomAttributeProperties (ca, type);
201                         MarkCustomAttributeFields (ca, type);
202                 }
203
204                 void MarkCustomAttributeProperties (CustomAttribute ca, TypeDefinition attribute)
205                 {
206                         foreach (var named_argument in ca.Properties) {
207                                 PropertyDefinition property = GetProperty (attribute, named_argument.Name);
208                                 if (property != null)
209                                         MarkMethod (property.SetMethod);
210
211                                 MarkIfType (named_argument.Argument);
212                         }
213                 }
214
215                 PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
216                 {
217                         while (type != null) {
218                                 PropertyDefinition property = type.Properties.FirstOrDefault (p => p.Name == propertyname);
219                                 if (property != null)
220                                         return property;
221
222                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
223                         }
224
225                         return null;
226                 }
227
228                 void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition attribute)
229                 {
230                         foreach (var named_argument in ca.Fields) {
231                                 FieldDefinition field = GetField (attribute, named_argument.Name);
232                                 if (field != null)
233                                         MarkField (field);
234
235                                 MarkIfType (named_argument.Argument);
236                         }
237                 }
238
239                 FieldDefinition GetField (TypeDefinition type, string fieldname)
240                 {
241                         while (type != null) {
242                                 FieldDefinition field = type.Fields.FirstOrDefault (f => f.Name == fieldname);
243                                 if (field != null)
244                                         return field;
245
246                                 type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
247                         }
248
249                         return null;
250                 }
251
252                 void MarkCustomAttributeArguments (CustomAttribute ca)
253                 {
254                         foreach (var argument in ca.ConstructorArguments)
255                                 MarkIfType (argument);
256                 }
257
258                 void MarkIfType (CustomAttributeArgument argument)
259                 {
260                         if (argument.Type.FullName != "System.Type")
261                                 return;
262
263                         MarkType (argument.Type);
264                         MarkType ((TypeReference) argument.Value);
265                 }
266
267                 protected bool CheckProcessed (IMetadataTokenProvider provider)
268                 {
269                         if (Annotations.IsProcessed (provider))
270                                 return true;
271
272                         Annotations.Processed (provider);
273                         return false;
274                 }
275
276                 void MarkAssembly (AssemblyDefinition assembly)
277                 {
278                         if (CheckProcessed (assembly))
279                                 return;
280
281                         MarkCustomAttributes (assembly);
282
283                         foreach (ModuleDefinition module in assembly.Modules)
284                                 MarkCustomAttributes (module);
285                 }
286
287                 void MarkField (FieldReference reference)
288                 {
289 //                      if (IgnoreScope (reference.DeclaringType.Scope))
290 //                              return;
291
292                         if (reference.DeclaringType is GenericInstanceType)
293                                 MarkType (reference.DeclaringType);
294
295                         FieldDefinition field = ResolveFieldDefinition (reference);
296
297                         if (field == null)
298                                 throw new ResolutionException (reference);
299
300                         if (CheckProcessed (field))
301                                 return;
302
303                         MarkType (field.DeclaringType);
304                         MarkType (field.FieldType);
305                         MarkCustomAttributes (field);
306                         MarkMarshalSpec (field);
307
308                         Annotations.Mark (field);
309                 }
310
311                 protected virtual bool IgnoreScope (IMetadataScope scope)
312                 {
313                         AssemblyDefinition assembly = ResolveAssembly (scope);
314                         return Annotations.GetAction (assembly) != AssemblyAction.Link;
315                 }
316
317                 FieldDefinition ResolveFieldDefinition (FieldReference field)
318                 {
319                         FieldDefinition fd = field as FieldDefinition;
320                         if (fd == null)
321                                 fd = field.Resolve ();
322
323                         return fd;
324                 }
325
326                 void MarkScope (IMetadataScope scope)
327                 {
328                         var provider = scope as IMetadataTokenProvider;
329                         if (provider == null)
330                                 return;
331
332                         Annotations.Mark (provider);
333                 }
334
335                 protected virtual TypeDefinition MarkType (TypeReference reference)
336                 {
337                         if (reference == null)
338                                 return null;
339
340                         reference = GetOriginalType (reference);
341
342                         if (reference is GenericParameter)
343                                 return null;
344
345 //                      if (IgnoreScope (reference.Scope))
346 //                              return;
347
348                         TypeDefinition type = ResolveTypeDefinition (reference);
349
350                         if (type == null)
351                                 throw new ResolutionException (reference);
352
353                         if (CheckProcessed (type))
354                                 return null;
355
356                         MarkScope (type.Scope);
357                         MarkType (type.BaseType);
358                         MarkType (type.DeclaringType);
359                         MarkCustomAttributes (type);
360
361                         if (IsMulticastDelegate (type)) {
362                                 MarkMethodCollection (type.Methods);
363                         }
364
365                         if (IsSerializable (type) && type.HasMethods) {
366                                 MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
367                                 MarkMethodsIf (type.Methods, IsSpecialSerializationConstructorPredicate);
368                         }
369
370                         MarkTypeSpecialCustomAttributes (type);
371
372                         MarkGenericParameterProvider (type);
373
374                         // keep fields for value-types and for classes with LayoutKind.Sequential or Explicit
375                         if (type.IsValueType || !type.IsAutoLayout)
376                                 MarkFields (type, type.IsEnum);
377
378                         if (type.HasInterfaces) {
379                                 foreach (TypeReference iface in type.Interfaces)
380                                         MarkType (iface);
381                         }
382
383                         if (type.HasMethods) {
384                                 MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
385                                 MarkMethodsIf (type.Methods, IsStaticConstructorPredicate);
386                         }
387
388                         Annotations.Mark (type);
389
390                         ApplyPreserveInfo (type);
391
392                         return type;
393                 }
394
395                 void MarkTypeSpecialCustomAttributes (TypeDefinition type)
396                 {
397                         if (!type.HasCustomAttributes)
398                                 return;
399
400                         foreach (CustomAttribute attribute in type.CustomAttributes) {
401                                 switch (attribute.Constructor.DeclaringType.FullName) {
402                                 case "System.Xml.Serialization.XmlSchemaProviderAttribute":
403                                         MarkXmlSchemaProvider (type, attribute);
404                                         break;
405                                 }
406                         }
407                 }
408
409                 void MarkMethodSpecialCustomAttributes (MethodDefinition method)
410                 {
411                         if (!method.HasCustomAttributes)
412                                 return;
413
414                         foreach (CustomAttribute attribute in method.CustomAttributes) {
415                                 switch (attribute.Constructor.DeclaringType.FullName) {
416                                 case "System.Web.Services.Protocols.SoapHeaderAttribute":
417                                         MarkSoapHeader (method, attribute);
418                                         break;
419                                 }
420                         }
421                 }
422
423                 void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
424                 {
425                         string method_name;
426                         if (!TryGetStringArgument (attribute, out method_name))
427                                 return;
428
429                         MarkNamedMethod (type, method_name);
430                 }
431
432                 static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
433                 {
434                         argument = null;
435
436                         if (attribute.ConstructorArguments.Count < 1)
437                                 return false;
438
439                         argument = attribute.ConstructorArguments [0].Value as string;
440
441                         return argument != null;
442                 }
443
444                 protected void MarkNamedMethod (TypeDefinition type, string method_name)
445                 {
446                         if (!type.HasMethods)
447                                 return;
448
449                         foreach (MethodDefinition method in type.Methods) {
450                                 if (method.Name != method_name)
451                                         continue;
452
453                                 MarkMethod (method);
454                         }
455                 }
456
457                 void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
458                 {
459                         string member_name;
460                         if (!TryGetStringArgument (attribute, out member_name))
461                                 return;
462
463                         MarkNamedField (method.DeclaringType, member_name);
464                         MarkNamedProperty (method.DeclaringType, member_name);
465                 }
466
467                 void MarkNamedField (TypeDefinition type, string field_name)
468                 {
469                         if (!type.HasFields)
470                                 return;
471
472                         foreach (FieldDefinition field in type.Fields) {
473                                 if (field.Name != field_name)
474                                         continue;
475
476                                 MarkField (field);
477                         }
478                 }
479
480                 void MarkNamedProperty (TypeDefinition type, string property_name)
481                 {
482                         if (!type.HasProperties)
483                                 return;
484
485                         foreach (PropertyDefinition property in type.Properties) {
486                                 if (property.Name != property_name)
487                                         continue;
488
489                                 MarkMethod (property.GetMethod);
490                                 MarkMethod (property.SetMethod);
491                         }
492                 }
493
494                 void MarkGenericParameterProvider (IGenericParameterProvider provider)
495                 {
496                         if (!provider.HasGenericParameters)
497                                 return;
498
499                         foreach (GenericParameter parameter in provider.GenericParameters)
500                                 MarkGenericParameter (parameter);
501                 }
502
503                 void MarkGenericParameter (GenericParameter parameter)
504                 {
505                         MarkCustomAttributes (parameter);
506                         foreach (TypeReference constraint in parameter.Constraints)
507                                 MarkType (constraint);
508                 }
509
510                 bool IsVirtualAndHasPreservedParent (MethodDefinition method)
511                 {
512                         if (!method.IsVirtual)
513                                 return false;
514
515                         var base_list = Annotations.GetBaseMethods (method);
516                         if (base_list == null)
517                                 return false;
518
519                         foreach (MethodDefinition @base in base_list) {
520                                 if (IgnoreScope (@base.DeclaringType.Scope))
521                                         return true;
522
523                                 if (IsVirtualAndHasPreservedParent (@base))
524                                         return true;
525                         }
526
527                         return false;
528                 }
529
530                 static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
531
532                 static bool IsSpecialSerializationConstructor (MethodDefinition method)
533                 {
534                         if (!IsConstructor (method))
535                                 return false;
536
537                         var parameters = method.Parameters;
538                         if (parameters.Count != 2)
539                                 return false;
540
541                         return parameters [0].ParameterType.Name == "SerializationInfo" &&
542                                 parameters [1].ParameterType.Name == "StreamingContext";
543                 }
544
545                 delegate bool MethodPredicate (MethodDefinition method);
546
547                 void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
548                 {
549                         foreach (MethodDefinition method in methods)
550                                 if (predicate (method))
551                                         MarkMethod (method);
552                 }
553
554                 static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
555
556                 static bool IsDefaultConstructor (MethodDefinition method)
557                 {
558                         return IsConstructor (method) && method.Parameters.Count == 0;
559                 }
560
561                 static bool IsConstructor (MethodDefinition method)
562                 {
563                         return method.IsConstructor && !method.IsStatic;
564                 }
565
566                 static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
567
568                 static bool IsStaticConstructor (MethodDefinition method)
569                 {
570                         return method.IsConstructor && method.IsStatic;
571                 }
572
573                 static bool IsSerializable (TypeDefinition td)
574                 {
575                         return (td.Attributes & TypeAttributes.Serializable) != 0;
576                 }
577
578                 static bool IsMulticastDelegate (TypeDefinition td)
579                 {
580                         return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
581                 }
582
583                 protected TypeDefinition ResolveTypeDefinition (TypeReference type)
584                 {
585                         TypeDefinition td = type as TypeDefinition;
586                         if (td == null)
587                                 td = type.Resolve ();
588
589                         return td;
590                 }
591
592                 protected TypeReference GetOriginalType (TypeReference type)
593                 {
594                         while (type is TypeSpecification) {
595                                 GenericInstanceType git = type as GenericInstanceType;
596                                 if (git != null)
597                                         MarkGenericArguments (git);
598
599                                 var mod = type as IModifierType;
600                                 if (mod != null)
601                                         MarkModifierType (mod);
602
603                                 type = ((TypeSpecification) type).ElementType;
604                         }
605
606                         return type;
607                 }
608
609                 void MarkModifierType (IModifierType mod)
610                 {
611                         MarkType (mod.ModifierType);
612                 }
613
614                 void MarkGenericArguments (IGenericInstance instance)
615                 {
616                         foreach (TypeReference argument in instance.GenericArguments)
617                                 MarkType (argument);
618
619                         MarkGenericArgumentConstructors (instance);
620                 }
621
622                 void MarkGenericArgumentConstructors (IGenericInstance instance)
623                 {
624                         var arguments = instance.GenericArguments;
625
626                         var generic_element = GetGenericProviderFromInstance (instance);
627                         if (generic_element == null)
628                                 return;
629
630                         var parameters = generic_element.GenericParameters;
631
632                         if (arguments.Count != parameters.Count)
633                                 return;
634
635                         for (int i = 0; i < arguments.Count; i++) {
636                                 var argument = arguments [i];
637                                 var parameter = parameters [i];
638
639                                 if (!parameter.HasDefaultConstructorConstraint)
640                                         continue;
641
642                                 var argument_definition = ResolveTypeDefinition (argument);
643                                 if (argument_definition == null)
644                                         continue;
645
646                                 MarkMethodsIf (argument_definition.Methods, ctor => !ctor.IsStatic && !ctor.HasParameters);
647                         }
648                 }
649
650                 IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
651                 {
652                         var method = instance as GenericInstanceMethod;
653                         if (method != null)
654                                 return ResolveMethodDefinition (method.ElementMethod);
655
656                         var type = instance as GenericInstanceType;
657                         if (type != null)
658                                 return ResolveTypeDefinition (type.ElementType);
659
660                         return null;
661                 }
662
663                 void ApplyPreserveInfo (TypeDefinition type)
664                 {
665                         ApplyPreserveMethods (type);
666
667                         if (!Annotations.IsPreserved (type))
668                                 return;
669
670                         switch (Annotations.GetPreserve (type)) {
671                         case TypePreserve.All:
672                                 MarkFields (type, true);
673                                 MarkMethods (type);
674                                 break;
675                         case TypePreserve.Fields:
676                                 MarkFields (type, true);
677                                 break;
678                         case TypePreserve.Methods:
679                                 MarkMethods (type);
680                                 break;
681                         }
682                 }
683
684                 void ApplyPreserveMethods (TypeDefinition type)
685                 {
686                         var list = Annotations.GetPreservedMethods (type);
687                         if (list == null)
688                                 return;
689
690                         MarkMethodCollection (list);
691                 }
692
693                 void ApplyPreserveMethods (MethodDefinition method)
694                 {
695                         var list = Annotations.GetPreservedMethods (method);
696                         if (list == null)
697                                 return;
698
699                         MarkMethodCollection (list);
700                 }
701
702                 protected void MarkFields (TypeDefinition type, bool includeStatic)
703                 {
704                         if (!type.HasFields)
705                                 return;
706
707                         foreach (FieldDefinition field in type.Fields) {
708                                 if (!includeStatic && field.IsStatic)
709                                         continue;
710                                 MarkField (field);
711                         }
712                 }
713
714                 protected virtual void MarkMethods (TypeDefinition type)
715                 {
716                         if (type.HasMethods)
717                                 MarkMethodCollection (type.Methods);
718                 }
719
720                 void MarkMethodCollection (IEnumerable methods)
721                 {
722                         foreach (MethodDefinition method in methods)
723                                 MarkMethod (method);
724                 }
725
726                 protected void MarkMethod (MethodReference reference)
727                 {
728                         reference = GetOriginalMethod (reference);
729
730                         if (reference.DeclaringType is ArrayType)
731                                 return;
732
733                         if (reference.DeclaringType is GenericInstanceType)
734                                 MarkType (reference.DeclaringType);
735
736 //                      if (IgnoreScope (reference.DeclaringType.Scope))
737 //                              return;
738
739                         MethodDefinition method = ResolveMethodDefinition (reference);
740
741                         if (method == null)
742                                 throw new ResolutionException (reference);
743
744                         if (Annotations.GetAction (method) == MethodAction.Nothing)
745                                 Annotations.SetAction (method, MethodAction.Parse);
746
747                         EnqueueMethod (method);
748                 }
749
750                 AssemblyDefinition ResolveAssembly (IMetadataScope scope)
751                 {
752                         AssemblyDefinition assembly = _context.Resolve (scope);
753                         MarkAssembly (assembly);
754                         return assembly;
755                 }
756
757                 protected MethodReference GetOriginalMethod (MethodReference method)
758                 {
759                         while (method is MethodSpecification) {
760                                 GenericInstanceMethod gim = method as GenericInstanceMethod;
761                                 if (gim != null)
762                                         MarkGenericArguments (gim);
763
764                                 method = ((MethodSpecification) method).ElementMethod;
765                         }
766
767                         return method;
768                 }
769
770                 MethodDefinition ResolveMethodDefinition (MethodReference method)
771                 {
772                         MethodDefinition md = method as MethodDefinition;
773                         if (md == null)
774                                 md = method.Resolve ();
775
776                         return md;
777                 }
778
779                 protected virtual void ProcessMethod (MethodDefinition method)
780                 {
781                         if (CheckProcessed (method))
782                                 return;
783
784                         MarkType (method.DeclaringType);
785                         MarkCustomAttributes (method);
786
787                         MarkGenericParameterProvider (method);
788
789                         if (IsPropertyMethod (method))
790                                 MarkProperty (GetProperty (method));
791                         else if (IsEventMethod (method))
792                                 MarkEvent (GetEvent (method));
793
794                         if (method.HasParameters) {
795                                 foreach (ParameterDefinition pd in method.Parameters) {
796                                         MarkType (pd.ParameterType);
797                                         MarkCustomAttributes (pd);
798                                         MarkMarshalSpec (pd);
799                                 }
800                         }
801
802                         if (method.HasOverrides) {
803                                 foreach (MethodReference ov in method.Overrides)
804                                         MarkMethod (ov);
805                         }
806
807                         MarkMethodSpecialCustomAttributes (method);
808
809                         if (method.IsVirtual)
810                                 _virtual_methods.Add (method);
811
812                         MarkBaseMethods (method);
813
814                         MarkType (method.ReturnType);
815                         MarkCustomAttributes (method.MethodReturnType);
816                         MarkMarshalSpec (method.MethodReturnType);
817
818                         if (ShouldParseMethodBody (method))
819                                 MarkMethodBody (method.Body);
820
821                         Annotations.Mark (method);
822
823                         ApplyPreserveMethods (method);
824                 }
825
826                 void MarkBaseMethods (MethodDefinition method)
827                 {
828                         IList base_methods = Annotations.GetBaseMethods (method);
829                         if (base_methods == null)
830                                 return;
831
832                         foreach (MethodDefinition base_method in base_methods) {
833                                 MarkMethod (base_method);
834                                 MarkBaseMethods (base_method);
835                         }
836                 }
837
838                 bool ShouldParseMethodBody (MethodDefinition method)
839                 {
840                         if (!method.HasBody)
841                                 return false;
842
843                         AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope);
844                         return (Annotations.GetAction (method) == MethodAction.ForceParse ||
845                                 (Annotations.GetAction (assembly) == AssemblyAction.Link && Annotations.GetAction (method) == MethodAction.Parse));
846                 }
847
848                 static bool IsPropertyMethod (MethodDefinition md)
849                 {
850                         return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 ||
851                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
852                 }
853
854                 static bool IsEventMethod (MethodDefinition md)
855                 {
856                         return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
857                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 ||
858                                 (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
859                 }
860
861                 static PropertyDefinition GetProperty (MethodDefinition md)
862                 {
863                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
864                         foreach (PropertyDefinition prop in declaringType.Properties)
865                                 if (prop.GetMethod == md || prop.SetMethod == md)
866                                         return prop;
867
868                         return null;
869                 }
870
871                 static EventDefinition GetEvent (MethodDefinition md)
872                 {
873                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
874                         foreach (EventDefinition evt in declaringType.Events)
875                                 if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md)
876                                         return evt;
877
878                         return null;
879                 }
880
881                 void MarkProperty (PropertyDefinition prop)
882                 {
883                         MarkCustomAttributes (prop);
884                 }
885
886                 void MarkEvent (EventDefinition evt)
887                 {
888                         MarkCustomAttributes (evt);
889                         MarkMethodIfNotNull (evt.AddMethod);
890                         MarkMethodIfNotNull (evt.InvokeMethod);
891                         MarkMethodIfNotNull (evt.RemoveMethod);
892                 }
893
894                 void MarkMethodIfNotNull (MethodReference method)
895                 {
896                         if (method == null)
897                                 return;
898
899                         MarkMethod (method);
900                 }
901
902                 protected virtual void MarkMethodBody (MethodBody body)
903                 {
904                         foreach (VariableDefinition var in body.Variables)
905                                 MarkType (var.VariableType);
906
907                         foreach (ExceptionHandler eh in body.ExceptionHandlers)
908                                 if (eh.HandlerType == ExceptionHandlerType.Catch)
909                                         MarkType (eh.CatchType);
910
911                         foreach (Instruction instruction in body.Instructions)
912                                 MarkInstruction (instruction);
913                 }
914
915                 protected virtual void MarkInstruction (Instruction instruction)
916                 {
917                         switch (instruction.OpCode.OperandType) {
918                         case OperandType.InlineField:
919                                 MarkField ((FieldReference) instruction.Operand);
920                                 break;
921                         case OperandType.InlineMethod:
922                                 MarkMethod ((MethodReference) instruction.Operand);
923                                 break;
924                         case OperandType.InlineTok:
925                                 object token = instruction.Operand;
926                                 if (token is TypeReference)
927                                         MarkType ((TypeReference) token);
928                                 else if (token is MethodReference)
929                                         MarkMethod ((MethodReference) token);
930                                 else
931                                         MarkField ((FieldReference) token);
932                                 break;
933                         case OperandType.InlineType:
934                                 MarkType ((TypeReference) instruction.Operand);
935                                 break;
936                         default:
937                                 break;
938                         }
939                 }
940         }
941 }