Wed Feb 24 15:47:16 CET 2010 Paolo Molaro <lupus@ximian.com>
[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                         TypeDefinition type = _context.GetType ((string) value);
283
284                         MarkType (type);
285                 }
286
287                 protected static bool CheckProcessed (IAnnotationProvider provider)
288                 {
289                         if (Annotations.IsProcessed (provider))
290                                 return true;
291
292                         Annotations.Processed (provider);
293                         return false;
294                 }
295
296                 void MarkAssembly (AssemblyDefinition assembly)
297                 {
298                         if (CheckProcessed (assembly))
299                                 return;
300
301                         MarkCustomAttributes (assembly);
302
303                         foreach (ModuleDefinition module in assembly.Modules)
304                                 MarkCustomAttributes (module);
305                 }
306
307                 void MarkField (FieldReference reference)
308                 {
309 //                      if (IgnoreScope (reference.DeclaringType.Scope))
310 //                              return;
311
312                         FieldDefinition field = ResolveFieldDefinition (reference);
313
314                         if (field == null)
315                                 throw new ResolutionException (reference);
316
317                         if (CheckProcessed (field))
318                                 return;
319
320                         MarkType (field.DeclaringType);
321                         MarkType (field.FieldType);
322                         MarkCustomAttributes (field);
323                         MarkMarshalSpec (field);
324
325                         Annotations.Mark (field);
326                 }
327
328                 protected virtual bool IgnoreScope (IMetadataScope scope)
329                 {
330                         AssemblyDefinition assembly = ResolveAssembly (scope);
331                         return Annotations.GetAction (assembly) != AssemblyAction.Link;
332                 }
333
334                 FieldDefinition ResolveFieldDefinition (FieldReference field)
335                 {
336                         FieldDefinition fd = field as FieldDefinition;
337                         if (fd == null)
338                                 fd = field.Resolve ();
339
340                         return fd;
341                 }
342
343                 void MarkScope (IMetadataScope scope)
344                 {
345                         IAnnotationProvider provider = scope as IAnnotationProvider;
346                         if (provider == null)
347                                 return;
348
349                         Annotations.Mark (provider);
350                 }
351
352                 protected virtual void MarkType (TypeReference reference)
353                 {
354                         if (reference == null)
355                                 return;
356
357                         reference = GetOriginalType (reference);
358
359                         if (reference is GenericParameter)
360                                 return;
361
362 //                      if (IgnoreScope (reference.Scope))
363 //                              return;
364
365                         TypeDefinition type = ResolveTypeDefinition (reference);
366
367                         if (type == null)
368                                 throw new ResolutionException (reference);
369
370                         if (CheckProcessed (type))
371                                 return;
372
373                         MarkScope (type.Scope);
374                         MarkType (type.BaseType);
375                         MarkType (type.DeclaringType);
376                         MarkCustomAttributes (type);
377
378                         if (IsMulticastDelegate (type)) {
379                                 MarkMethodCollection (type.Constructors);
380                                 MarkMethodCollection (type.Methods);
381                         }
382
383                         if (IsSerializable (type) && type.HasConstructors) {
384                                 MarkMethodsIf (type.Constructors, IsDefaultConstructorPredicate);
385                                 MarkMethodsIf (type.Constructors, IsSpecialSerializationConstructorPredicate);
386                         }
387
388                         MarkTypeSpecialCustomAttributes (type);
389
390                         MarkGenericParameterProvider (type);
391
392                         if (type.IsValueType)
393                                 MarkFields (type);
394
395                         if (type.HasInterfaces) {
396                                 foreach (TypeReference iface in type.Interfaces)
397                                         MarkType (iface);
398                         }
399
400                         if (type.HasMethods)
401                                 MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
402
403                         if (type.HasConstructors)
404                                 MarkMethodsIf (type.Constructors, IsStaticConstructorPredicate);
405
406                         Annotations.Mark (type);
407
408                         ApplyPreserveInfo (type);
409                 }
410
411                 void MarkTypeSpecialCustomAttributes (TypeDefinition type)
412                 {
413                         if (!type.HasCustomAttributes)
414                                 return;
415
416                         foreach (CustomAttribute attribute in type.CustomAttributes) {
417                                 switch (attribute.Constructor.DeclaringType.FullName) {
418                                 case "System.Xml.Serialization.XmlSchemaProviderAttribute":
419                                         MarkXmlSchemaProvider (type, attribute);
420                                         break;
421                                 }
422                         }
423                 }
424
425                 void MarkMethodSpecialCustomAttributes (MethodDefinition method)
426                 {
427                         if (!method.HasCustomAttributes)
428                                 return;
429
430                         foreach (CustomAttribute attribute in method.CustomAttributes) {
431                                 switch (attribute.Constructor.DeclaringType.FullName) {
432                                 case "System.Web.Services.Protocols.SoapHeaderAttribute":
433                                         MarkSoapHeader (method, attribute);
434                                         break;
435                                 }
436                         }
437                 }
438
439                 void MarkXmlSchemaProvider (TypeDefinition type, CustomAttribute attribute)
440                 {
441                         string method_name;
442                         if (!TryGetStringArgument (attribute, out method_name))
443                                 return;
444
445                         MarkNamedMethod (type, method_name);
446                 }
447
448                 static bool TryGetStringArgument (CustomAttribute attribute, out string argument)
449                 {
450                         argument = null;
451
452                         if (!attribute.Resolved || attribute.ConstructorParameters.Count < 1)
453                                 return false;
454
455                         argument = attribute.ConstructorParameters [0] as string;
456
457                         return argument != null;
458                 }
459
460                 void MarkNamedMethod (TypeDefinition type, string method_name)
461                 {
462                         if (!type.HasMethods)
463                                 return;
464
465                         foreach (MethodDefinition method in type.Methods) {
466                                 if (method.Name != method_name)
467                                         continue;
468
469                                 MarkMethod (method);
470                         }
471                 }
472
473                 void MarkSoapHeader (MethodDefinition method, CustomAttribute attribute)
474                 {
475                         string member_name;
476                         if (!TryGetStringArgument (attribute, out member_name))
477                                 return;
478
479                         MarkNamedField (method.DeclaringType, member_name);
480                         MarkNamedProperty (method.DeclaringType, member_name);
481                 }
482
483                 void MarkNamedField (TypeDefinition type, string field_name)
484                 {
485                         if (!type.HasFields)
486                                 return;
487
488                         foreach (FieldDefinition field in type.Fields) {
489                                 if (field.Name != field_name)
490                                         continue;
491
492                                 MarkField (field);
493                         }
494                 }
495
496                 void MarkNamedProperty (TypeDefinition type, string property_name)
497                 {
498                         if (!type.HasProperties)
499                                 return;
500
501                         foreach (PropertyDefinition property in type.Properties) {
502                                 if (property.Name != property_name)
503                                         continue;
504
505                                 MarkMethod (property.GetMethod);
506                                 MarkMethod (property.SetMethod);
507                         }
508                 }
509
510                 void MarkGenericParameterProvider (IGenericParameterProvider provider)
511                 {
512                         if (!provider.HasGenericParameters)
513                                 return;
514
515                         foreach (GenericParameter parameter in provider.GenericParameters)
516                                 MarkGenericParameter (parameter);
517                 }
518
519                 void MarkGenericParameter (GenericParameter parameter)
520                 {
521                         MarkCustomAttributes (parameter);
522                         foreach (TypeReference constraint in parameter.Constraints)
523                                 MarkType (constraint);
524                 }
525
526                 bool IsVirtualAndHasPreservedParent (MethodDefinition method)
527                 {
528                         if (!method.IsVirtual)
529                                 return false;
530
531                         var base_list = Annotations.GetBaseMethods (method);
532                         if (base_list == null)
533                                 return false;
534
535                         foreach (MethodDefinition @base in base_list) {
536                                 if (IgnoreScope (@base.DeclaringType.Scope))
537                                         return true;
538
539                                 if (IsVirtualAndHasPreservedParent (@base))
540                                         return true;
541                         }
542
543                         return false;
544                 }
545
546                 static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
547
548                 static bool IsSpecialSerializationConstructor (MethodDefinition method)
549                 {
550                         if (!IsConstructor (method))
551                                 return false;
552
553                         ParameterDefinitionCollection parameters = method.Parameters;
554                         if (parameters.Count != 2)
555                                 return false;
556
557                         return parameters [0].ParameterType.Name == "SerializationInfo" &&
558                                 parameters [1].ParameterType.Name == "StreamingContext";
559                 }
560
561                 delegate bool MethodPredicate (MethodDefinition method);
562
563                 void MarkMethodsIf (ICollection methods, MethodPredicate predicate)
564                 {
565                         foreach (MethodDefinition method in methods)
566                                 if (predicate (method))
567                                         MarkMethod (method);
568                 }
569
570                 static MethodPredicate IsDefaultConstructorPredicate = new MethodPredicate (IsDefaultConstructor);
571
572                 static bool IsDefaultConstructor (MethodDefinition method)
573                 {
574                         return IsConstructor (method) && method.Parameters.Count == 0;
575                 }
576
577                 static bool IsConstructor (MethodDefinition method)
578                 {
579                         return method.Name == MethodDefinition.Ctor && method.IsSpecialName &&
580                                 method.IsRuntimeSpecialName;
581                 }
582
583                 static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
584
585                 static bool IsStaticConstructor (MethodDefinition method)
586                 {
587                         return method.Name == MethodDefinition.Cctor && method.IsSpecialName &&
588                                 method.IsRuntimeSpecialName;
589                 }
590
591                 static bool IsSerializable (TypeDefinition td)
592                 {
593                         return (td.Attributes & TypeAttributes.Serializable) != 0;
594                 }
595
596                 static bool IsMulticastDelegate (TypeDefinition td)
597                 {
598                         return td.BaseType != null && td.BaseType.FullName == "System.MulticastDelegate";
599                 }
600
601                 TypeDefinition ResolveTypeDefinition (TypeReference type)
602                 {
603                         TypeDefinition td = type as TypeDefinition;
604                         if (td == null)
605                                 td = type.Resolve ();
606
607                         return td;
608                 }
609
610                 protected TypeReference GetOriginalType (TypeReference type)
611                 {
612                         while (type is TypeSpecification) {
613                                 GenericInstanceType git = type as GenericInstanceType;
614                                 if (git != null)
615                                         MarkGenericArguments (git);
616
617                                 ModType mod = type as ModType;
618                                 if (mod != null)
619                                         MarkModifierType (mod);
620
621                                 type = ((TypeSpecification) type).ElementType;
622                         }
623
624                         return type;
625                 }
626
627                 void MarkModifierType (ModType mod)
628                 {
629                         MarkType (mod.ModifierType);
630                 }
631
632                 void MarkGenericArguments (IGenericInstance instance)
633                 {
634                         foreach (TypeReference argument in instance.GenericArguments)
635                                 MarkType (argument);
636
637                         MarkGenericArgumentConstructors (instance);
638                 }
639
640                 void MarkGenericArgumentConstructors (IGenericInstance instance)
641                 {
642                         var arguments = instance.GenericArguments;
643
644                         var generic_element = GetGenericProviderFromInstance (instance);
645                         if (generic_element == null)
646                                 return;
647
648                         var parameters = generic_element.GenericParameters;
649
650                         if (arguments.Count != parameters.Count)
651                                 return;
652
653                         for (int i = 0; i < arguments.Count; i++) {
654                                 var argument = arguments [i];
655                                 var parameter = parameters [i];
656
657                                 if (!parameter.HasDefaultConstructorConstraint)
658                                         continue;
659
660                                 var argument_definition = ResolveTypeDefinition (argument);
661                                 if (argument_definition == null)
662                                         continue;
663
664                                 MarkMethodsIf (argument_definition.Constructors, ctor => !ctor.IsStatic && !ctor.HasParameters);
665                         }
666                 }
667
668                 IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
669                 {
670                         var method = instance as GenericInstanceMethod;
671                         if (method != null)
672                                 return method.ElementMethod;
673
674                         var type = instance as GenericInstanceType;
675                         if (type != null)
676                                 return type.ElementType;
677
678                         return null;
679                 }
680
681                 void ApplyPreserveInfo (TypeDefinition type)
682                 {
683                         ApplyPreserveMethods (type);
684
685                         if (!Annotations.IsPreserved (type))
686                                 return;
687
688                         switch (Annotations.GetPreserve (type)) {
689                         case TypePreserve.All:
690                                 MarkFields (type);
691                                 MarkMethods (type);
692                                 break;
693                         case TypePreserve.Fields:
694                                 MarkFields (type);
695                                 break;
696                         case TypePreserve.Methods:
697                                 MarkMethods (type);
698                                 break;
699                         }
700                 }
701
702                 void ApplyPreserveMethods (TypeDefinition type)
703                 {
704                         var list = Annotations.GetPreservedMethods (type);
705                         if (list == null)
706                                 return;
707
708                         foreach (MethodDefinition method in list)
709                                 MarkMethod (method);
710                 }
711
712                 void MarkFields (TypeDefinition type)
713                 {
714                         if (!type.HasFields)
715                                 return;
716
717                         foreach (FieldDefinition field in type.Fields)
718                                 MarkField (field);
719                 }
720
721                 void MarkMethods (TypeDefinition type)
722                 {
723                         if (type.HasMethods)
724                                 MarkMethodCollection (type.Methods);
725                         if (type.HasConstructors)
726                                 MarkMethodCollection (type.Constructors);
727                 }
728
729                 void MarkMethodCollection (IEnumerable methods)
730                 {
731                         foreach (MethodDefinition method in methods)
732                                 MarkMethod (method);
733                 }
734
735                 void MarkMethod (MethodReference reference)
736                 {
737                         reference = GetOriginalMethod (reference);
738
739                         if (reference.DeclaringType is ArrayType)
740                                 return;
741
742 //                      if (IgnoreScope (reference.DeclaringType.Scope))
743 //                              return;
744
745                         MethodDefinition method = ResolveMethodDefinition (reference);
746
747                         if (method == null)
748                                 throw new ResolutionException (reference);
749
750                         if (Annotations.GetAction (method) == MethodAction.Nothing)
751                                 Annotations.SetAction (method, MethodAction.Parse);
752
753                         EnqueueMethod (method);
754                 }
755
756                 AssemblyDefinition ResolveAssembly (IMetadataScope scope)
757                 {
758                         AssemblyDefinition assembly = _context.Resolve (scope);
759                         MarkAssembly (assembly);
760                         return assembly;
761                 }
762
763                 MethodReference GetOriginalMethod (MethodReference method)
764                 {
765                         while (method is MethodSpecification) {
766                                 GenericInstanceMethod gim = method as GenericInstanceMethod;
767                                 if (gim != null)
768                                         MarkGenericArguments (gim);
769
770                                 method = ((MethodSpecification) method).ElementMethod;
771                         }
772
773                         return method;
774                 }
775
776                 MethodDefinition ResolveMethodDefinition (MethodReference method)
777                 {
778                         MethodDefinition md = method as MethodDefinition;
779                         if (md == null)
780                                 md = method.Resolve ();
781
782                         return md;
783                 }
784
785                 void ProcessMethod (MethodDefinition method)
786                 {
787                         if (CheckProcessed (method))
788                                 return;
789
790                         MarkType (method.DeclaringType);
791                         MarkCustomAttributes (method);
792
793                         MarkGenericParameterProvider (method);
794
795                         if (IsPropertyMethod (method))
796                                 MarkProperty (GetProperty (method));
797                         else if (IsEventMethod (method))
798                                 MarkEvent (GetEvent (method));
799
800                         if (method.HasParameters) {
801                                 foreach (ParameterDefinition pd in method.Parameters) {
802                                         MarkType (pd.ParameterType);
803                                         MarkCustomAttributes (pd);
804                                         MarkMarshalSpec (pd);
805                                 }
806                         }
807
808                         if (method.HasOverrides) {
809                                 foreach (MethodReference ov in method.Overrides)
810                                         MarkMethod (ov);
811                         }
812
813                         MarkMethodSpecialCustomAttributes (method);
814
815                         if (method.IsVirtual)
816                                 _virtual_methods.Add (method);
817
818                         MarkBaseMethods (method);
819
820                         MarkType (method.ReturnType.ReturnType);
821                         MarkCustomAttributes (method.ReturnType);
822                         MarkMarshalSpec (method.ReturnType);
823
824                         if (ShouldParseMethodBody (method))
825                                 MarkMethodBody (method.Body);
826
827                         Annotations.Mark (method);
828                 }
829
830                 void MarkBaseMethods (MethodDefinition method)
831                 {
832                         IList base_methods = Annotations.GetBaseMethods (method);
833                         if (base_methods == null)
834                                 return;
835
836                         foreach (MethodDefinition base_method in base_methods) {
837                                 MarkMethod (base_method);
838                                 MarkBaseMethods (base_method);
839                         }
840                 }
841
842                 bool ShouldParseMethodBody (MethodDefinition method)
843                 {
844                         if (!method.HasBody)
845                                 return false;
846
847                         AssemblyDefinition assembly = ResolveAssembly (method.DeclaringType.Scope);
848                         return (Annotations.GetAction (method) == MethodAction.ForceParse ||
849                                 (Annotations.GetAction (assembly) == AssemblyAction.Link && Annotations.GetAction (method) == MethodAction.Parse));
850                 }
851
852                 static bool IsPropertyMethod (MethodDefinition md)
853                 {
854                         return (md.SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0 ||
855                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
856                 }
857
858                 static bool IsEventMethod (MethodDefinition md)
859                 {
860                         return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 ||
861                                 (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 ||
862                                 (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
863                 }
864
865                 static PropertyDefinition GetProperty (MethodDefinition md)
866                 {
867                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
868                         foreach (PropertyDefinition prop in declaringType.Properties)
869                                 if (prop.GetMethod == md || prop.SetMethod == md)
870                                         return prop;
871
872                         return null;
873                 }
874
875                 static EventDefinition GetEvent (MethodDefinition md)
876                 {
877                         TypeDefinition declaringType = (TypeDefinition) md.DeclaringType;
878                         foreach (EventDefinition evt in declaringType.Events)
879                                 if (evt.AddMethod == md || evt.InvokeMethod == md || evt.RemoveMethod == md)
880                                         return evt;
881
882                         return null;
883                 }
884
885                 void MarkProperty (PropertyDefinition prop)
886                 {
887                         MarkCustomAttributes (prop);
888                 }
889
890                 void MarkEvent (EventDefinition evt)
891                 {
892                         MarkCustomAttributes (evt);
893                         MarkMethodIfNotNull (evt.AddMethod);
894                         MarkMethodIfNotNull (evt.InvokeMethod);
895                         MarkMethodIfNotNull (evt.RemoveMethod);
896                 }
897
898                 void MarkMethodIfNotNull (MethodReference method)
899                 {
900                         if (method == null)
901                                 return;
902
903                         MarkMethod (method);
904                 }
905
906                 void MarkInstruction (Instruction instruction)
907                 {
908                         switch (instruction.OpCode.OperandType) {
909                         case OperandType.InlineField:
910                                 MarkField ((FieldReference) instruction.Operand);
911                                 break;
912                         case OperandType.InlineMethod:
913                                 MarkMethod ((MethodReference) instruction.Operand);
914                                 break;
915                         case OperandType.InlineTok:
916                                 object token = instruction.Operand;
917                                 if (token is TypeReference)
918                                         MarkType ((TypeReference) token);
919                                 else if (token is MethodReference)
920                                         MarkMethod ((MethodReference) token);
921                                 else
922                                         MarkField ((FieldReference) token);
923                                 break;
924                         case OperandType.InlineType:
925                                 MarkType ((TypeReference) instruction.Operand);
926                                 break;
927                         default:
928                                 break;
929                         }
930                 }
931         }
932 }