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