Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs/tools
diff options
context:
space:
mode:
authorJb Evain <jbevain@gmail.com>2009-11-02 19:19:15 +0300
committerJb Evain <jbevain@gmail.com>2009-11-02 19:19:15 +0300
commitf21d6449faa5a005d769660de636a5b722ae4597 (patch)
treecc181700073c15646ada0de34bdb2257c7e9976d /mcs/tools
parent3e7cea123204e599765433d6c78b0a2521056d91 (diff)
2009-11-02 Jb Evain <jbevain@novell.com>
Merge the MonoTouch Linker branch. * monolinker.exe.sources: update * Mono.Linker/Annotations.cs: - add an preserved methods annotation on a type. - add an annotation to get the base methods of a method. - add an annotation to get the overriden method of a method. * Mono.Linker/AssemblyAction.cs: add a Delete action to remove an assembly from the output set. * Mono.Linker.Steps/TypeMapStep.cs: new step that create a map of virtual methods implementation. * Mono.Linker.Steps/MarkStep.cs: - removal of virtual methods. - fix for custom attributes assigning properties and field defined in a base type. - mark scopes. - mark default constructors of types used as a generic instance of a generic parameter constrained with new(). - apply preserved methods. * Mono.Linker.Steps/SweepStep.cs: remove unused assemblies. * Mono.Linker.Steps/LoadI18nAssemblies.cs: fix linking of i18n assemblies. * Mono.Linker.Steps/OutputStep.cs: fix the copied assemblies when the output directory is the same as the origin of the assemblies. * Mono.Linker.Steps/ResolveFromXmlStep.cs * Mono.Linker.Steps/ResolveFromAssemblyStep.cs * Mono.Linker.Steps/BaseStep.cs * Mono.Linker/Driver.cs * Mono.Linker/Pipeline.cs: Cosmetics. svn path=/branches/mono-2-6/mcs/; revision=145209
Diffstat (limited to 'mcs/tools')
-rw-r--r--mcs/tools/linker/ChangeLog42
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/BaseStep.cs4
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/LoadI18nAssemblies.cs2
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs224
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs19
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/ResolveFromAssemblyStep.cs2
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs2
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs61
-rw-r--r--mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs240
-rw-r--r--mcs/tools/linker/Mono.Linker/Annotations.cs57
-rw-r--r--mcs/tools/linker/Mono.Linker/AssemblyAction.cs3
-rw-r--r--mcs/tools/linker/Mono.Linker/Driver.cs3
-rw-r--r--mcs/tools/linker/Mono.Linker/Pipeline.cs3
-rw-r--r--mcs/tools/linker/monolinker.exe.sources1
14 files changed, 614 insertions, 49 deletions
diff --git a/mcs/tools/linker/ChangeLog b/mcs/tools/linker/ChangeLog
index f7dc1b39b0e..6b2dd5e0c69 100644
--- a/mcs/tools/linker/ChangeLog
+++ b/mcs/tools/linker/ChangeLog
@@ -1,3 +1,45 @@
+2009-11-02 Jb Evain <jbevain@novell.com>
+
+ Merge the MonoTouch Linker branch.
+
+ * monolinker.exe.sources: update
+
+ * Mono.Linker/Annotations.cs:
+ - add an preserved methods annotation on a type.
+ - add an annotation to get the base methods of a method.
+ - add an annotation to get the overriden method of a method.
+
+ * Mono.Linker/AssemblyAction.cs:
+ add a Delete action to remove an assembly from the output set.
+
+ * Mono.Linker.Steps/TypeMapStep.cs:
+ new step that create a map of virtual methods implementation.
+
+ * Mono.Linker.Steps/MarkStep.cs:
+ - removal of virtual methods.
+ - fix for custom attributes assigning properties and field
+ defined in a base type.
+ - mark scopes.
+ - mark default constructors of types used as a generic instance
+ of a generic parameter constrained with new().
+ - apply preserved methods.
+
+ * Mono.Linker.Steps/SweepStep.cs: remove unused assemblies.
+
+ * Mono.Linker.Steps/LoadI18nAssemblies.cs:
+ fix linking of i18n assemblies.
+
+ * Mono.Linker.Steps/OutputStep.cs:
+ fix the copied assemblies when the output directory
+ is the same as the origin of the assemblies.
+
+ * Mono.Linker.Steps/ResolveFromXmlStep.cs
+ * Mono.Linker.Steps/ResolveFromAssemblyStep.cs
+ * Mono.Linker.Steps/BaseStep.cs
+ * Mono.Linker/Driver.cs
+ * Mono.Linker/Pipeline.cs:
+ Cosmetics.
+
2009-09-10 Andrés G. Aragoneses <aaragoneses@novell.com>
* Mono.Linker.Steps/MarkStep.cs: Make IgnoreScope() virtual to
diff --git a/mcs/tools/linker/Mono.Linker.Steps/BaseStep.cs b/mcs/tools/linker/Mono.Linker.Steps/BaseStep.cs
index 40eda6109aa..696740ecd4b 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/BaseStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/BaseStep.cs
@@ -49,7 +49,7 @@ namespace Mono.Linker.Steps {
foreach (AssemblyDefinition assembly in context.GetAssemblies ())
ProcessAssembly (assembly);
-
+
EndProcess ();
}
@@ -61,7 +61,7 @@ namespace Mono.Linker.Steps {
protected virtual void Process ()
{
}
-
+
protected virtual void EndProcess ()
{
}
diff --git a/mcs/tools/linker/Mono.Linker.Steps/LoadI18nAssemblies.cs b/mcs/tools/linker/Mono.Linker.Steps/LoadI18nAssemblies.cs
index f45f05709ed..c8256a5c720 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/LoadI18nAssemblies.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/LoadI18nAssemblies.cs
@@ -77,7 +77,7 @@ namespace Mono.Linker.Steps {
void LoadAssembly (AssemblyNameReference name)
{
AssemblyDefinition assembly = Context.Resolve (name);
- Annotations.SetAction (assembly, AssemblyAction.Copy);
+ ResolveFromAssemblyStep.ProcessLibrary (assembly);
}
AssemblyNameReference GetAssemblyName (I18nAssemblies assembly)
diff --git a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs
index fa6ddc61aad..f68d6039d27 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/MarkStep.cs
@@ -37,11 +37,13 @@ namespace Mono.Linker.Steps {
public class MarkStep : IStep {
LinkContext _context;
- Queue _queue;
+ Queue _methods;
+ ArrayList _virtual_methods;
public MarkStep ()
{
- _queue = new Queue ();
+ _methods = new Queue ();
+ _virtual_methods = new ArrayList ();
}
public void Process (LinkContext context)
@@ -92,7 +94,7 @@ namespace Mono.Linker.Steps {
{
foreach (MethodDefinition method in methods)
if (Annotations.IsMarked (method))
- _queue.Enqueue (method);
+ EnqueueMethod (method);
}
void Process ()
@@ -101,19 +103,58 @@ namespace Mono.Linker.Steps {
throw new InvalidOperationException ("No entry methods");
while (!QueueIsEmpty ()) {
- MethodDefinition method = (MethodDefinition) _queue.Dequeue ();
+ ProcessQueue ();
+ ProcessVirtualMethods ();
+ }
+ }
+
+ void ProcessQueue ()
+ {
+ while (!QueueIsEmpty ()) {
+ MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
ProcessMethod (method);
}
}
bool QueueIsEmpty ()
{
- return _queue.Count == 0;
+ return _methods.Count == 0;
}
protected virtual void EnqueueMethod (MethodDefinition method)
{
- _queue.Enqueue (method);
+ _methods.Enqueue (method);
+ }
+
+ void ProcessVirtualMethods ()
+ {
+ foreach (MethodDefinition method in _virtual_methods)
+ ProcessVirtualMethod (method);
+ }
+
+ void ProcessVirtualMethod (MethodDefinition method)
+ {
+ IList overrides = Annotations.GetOverrides (method);
+ if (overrides == null)
+ return;
+
+ foreach (MethodDefinition @override in overrides)
+ ProcessOverride (@override);
+ }
+
+ void ProcessOverride (MethodDefinition method)
+ {
+ if (!Annotations.IsMarked (method.DeclaringType))
+ return;
+
+ if (Annotations.IsProcessed (method))
+ return;
+
+ if (Annotations.IsMarked (method))
+ return;
+
+ MarkMethod (method);
+ ProcessVirtualMethod (method);
}
void MarkMethodBody (MethodBody body)
@@ -176,22 +217,34 @@ namespace Mono.Linker.Steps {
foreach (DictionaryEntry de in ca.Properties) {
string propertyname = (string) de.Key;
- PropertyDefinition [] properties = attribute.Properties.GetProperties (propertyname);
-
- if (properties != null && properties.Length != 0 && properties [0].SetMethod != null)
- MarkMethod (properties [0].SetMethod);
+ PropertyDefinition property = GetProperty (attribute, propertyname);
+ if (property != null)
+ MarkMethod (property.SetMethod);
TypeReference propType = ca.GetPropertyType (propertyname);
MarkIfType (propType, de.Value);
}
}
+ PropertyDefinition GetProperty (TypeDefinition type, string propertyname)
+ {
+ while (type != null) {
+ PropertyDefinition [] properties = type.Properties.GetProperties (propertyname);
+ if (properties != null && properties.Length != 0 && properties [0].SetMethod != null)
+ return properties [0];
+
+ type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
+ }
+
+ return null;
+ }
+
void MarkCustomAttributeFields (CustomAttribute ca, TypeDefinition attribute)
{
foreach (DictionaryEntry de in ca.Fields) {
string fieldname = (string) de.Key;
- FieldDefinition field = attribute.Fields.GetField (fieldname);
+ FieldDefinition field = GetField (attribute, fieldname);
if (field != null)
MarkField (field);
@@ -200,6 +253,19 @@ namespace Mono.Linker.Steps {
}
}
+ FieldDefinition GetField (TypeDefinition type, string fieldname)
+ {
+ while (type != null) {
+ FieldDefinition field = type.Fields.GetField (fieldname);
+ if (field != null)
+ return field;
+
+ type = type.BaseType != null ? ResolveTypeDefinition (type.BaseType) : null;
+ }
+
+ return null;
+ }
+
void MarkCustomAttributeParameters (CustomAttribute ca)
{
for (int i = 0; i < ca.Constructor.Parameters.Count; i++) {
@@ -240,8 +306,8 @@ namespace Mono.Linker.Steps {
void MarkField (FieldReference reference)
{
- if (IgnoreScope (reference.DeclaringType.Scope))
- return;
+// if (IgnoreScope (reference.DeclaringType.Scope))
+// return;
FieldDefinition field = ResolveFieldDefinition (reference);
@@ -274,6 +340,15 @@ namespace Mono.Linker.Steps {
return fd;
}
+ void MarkScope (IMetadataScope scope)
+ {
+ IAnnotationProvider provider = scope as IAnnotationProvider;
+ if (provider == null)
+ return;
+
+ Annotations.Mark (provider);
+ }
+
protected virtual void MarkType (TypeReference reference)
{
if (reference == null)
@@ -284,8 +359,8 @@ namespace Mono.Linker.Steps {
if (reference is GenericParameter)
return;
- if (IgnoreScope (reference.Scope))
- return;
+// if (IgnoreScope (reference.Scope))
+// return;
TypeDefinition type = ResolveTypeDefinition (reference);
@@ -295,12 +370,15 @@ namespace Mono.Linker.Steps {
if (CheckProcessed (type))
return;
+ MarkScope (type.Scope);
MarkType (type.BaseType);
MarkType (type.DeclaringType);
- MarkCustomAttributes(type);
+ MarkCustomAttributes (type);
- if (IsMulticastDelegate (type))
+ if (IsMulticastDelegate (type)) {
MarkMethodCollection (type.Constructors);
+ MarkMethodCollection (type.Methods);
+ }
if (IsSerializable (type) && type.HasConstructors) {
MarkMethodsIf (type.Constructors, IsDefaultConstructorPredicate);
@@ -317,12 +395,12 @@ namespace Mono.Linker.Steps {
MarkType (iface);
}
+ if (type.HasMethods)
+ MarkMethodsIf (type.Methods, IsVirtualAndHasPreservedParent);
+
if (type.HasConstructors)
MarkMethodsIf (type.Constructors, IsStaticConstructorPredicate);
- if (type.HasMethods)
- MarkMethodsIf (type.Methods, IsVirtualPredicate);
-
Annotations.Mark (type);
ApplyPreserveInfo (type);
@@ -344,6 +422,26 @@ namespace Mono.Linker.Steps {
MarkType (constraint);
}
+ bool IsVirtualAndHasPreservedParent (MethodDefinition method)
+ {
+ if (!method.IsVirtual)
+ return false;
+
+ var base_list = Annotations.GetBaseMethods (method);
+ if (base_list == null)
+ return false;
+
+ foreach (MethodDefinition @base in base_list) {
+ if (IgnoreScope (@base.DeclaringType.Scope))
+ return true;
+
+ if (IsVirtualAndHasPreservedParent (@base))
+ return true;
+ }
+
+ return false;
+ }
+
static MethodPredicate IsSpecialSerializationConstructorPredicate = new MethodPredicate (IsSpecialSerializationConstructor);
static bool IsSpecialSerializationConstructor (MethodDefinition method)
@@ -381,13 +479,6 @@ namespace Mono.Linker.Steps {
method.IsRuntimeSpecialName;
}
- static MethodPredicate IsVirtualPredicate = new MethodPredicate (IsVirtual);
-
- static bool IsVirtual (MethodDefinition method)
- {
- return method.IsVirtual;
- }
-
static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
static bool IsStaticConstructor (MethodDefinition method)
@@ -441,10 +532,55 @@ namespace Mono.Linker.Steps {
{
foreach (TypeReference argument in instance.GenericArguments)
MarkType (argument);
+
+ MarkGenericArgumentConstructors (instance);
+ }
+
+ void MarkGenericArgumentConstructors (IGenericInstance instance)
+ {
+ var arguments = instance.GenericArguments;
+
+ var generic_element = GetGenericProviderFromInstance (instance);
+ if (generic_element == null)
+ return;
+
+ var parameters = generic_element.GenericParameters;
+
+ if (arguments.Count != parameters.Count)
+ return;
+
+ for (int i = 0; i < arguments.Count; i++) {
+ var argument = arguments [i];
+ var parameter = parameters [i];
+
+ if (!parameter.HasDefaultConstructorConstraint)
+ continue;
+
+ var argument_definition = ResolveTypeDefinition (argument);
+ if (argument_definition == null)
+ continue;
+
+ MarkMethodsIf (argument_definition.Constructors, ctor => !ctor.IsStatic && !ctor.HasParameters);
+ }
+ }
+
+ IGenericParameterProvider GetGenericProviderFromInstance (IGenericInstance instance)
+ {
+ var method = instance as GenericInstanceMethod;
+ if (method != null)
+ return method.ElementMethod;
+
+ var type = instance as GenericInstanceType;
+ if (type != null)
+ return type.ElementType;
+
+ return null;
}
void ApplyPreserveInfo (TypeDefinition type)
{
+ ApplyPreserveMethods (type);
+
if (!Annotations.IsPreserved (type))
return;
@@ -462,6 +598,16 @@ namespace Mono.Linker.Steps {
}
}
+ void ApplyPreserveMethods (TypeDefinition type)
+ {
+ var list = Annotations.GetPreservedMethods (type);
+ if (list == null)
+ return;
+
+ foreach (MethodDefinition method in list)
+ MarkMethod (method);
+ }
+
void MarkFields (TypeDefinition type)
{
if (!type.HasFields)
@@ -492,15 +638,16 @@ namespace Mono.Linker.Steps {
if (reference.DeclaringType is ArrayType)
return;
- if (IgnoreScope (reference.DeclaringType.Scope))
- return;
+// if (IgnoreScope (reference.DeclaringType.Scope))
+// return;
MethodDefinition method = ResolveMethodDefinition (reference);
if (method == null)
throw new ResolutionException (reference);
- Annotations.SetAction (method, MethodAction.Parse);
+ if (Annotations.GetAction (method) == MethodAction.Nothing)
+ Annotations.SetAction (method, MethodAction.Parse);
EnqueueMethod (method);
}
@@ -562,6 +709,11 @@ namespace Mono.Linker.Steps {
MarkMethod (ov);
}
+ if (method.IsVirtual)
+ _virtual_methods.Add (method);
+
+ MarkBaseMethods (method);
+
MarkType (method.ReturnType.ReturnType);
MarkCustomAttributes (method.ReturnType);
MarkMarshalSpec (method.ReturnType);
@@ -572,6 +724,18 @@ namespace Mono.Linker.Steps {
Annotations.Mark (method);
}
+ void MarkBaseMethods (MethodDefinition method)
+ {
+ IList base_methods = Annotations.GetBaseMethods (method);
+ if (base_methods == null)
+ return;
+
+ foreach (MethodDefinition base_method in base_methods) {
+ MarkMethod (base_method);
+ MarkBaseMethods (base_method);
+ }
+ }
+
bool ShouldParseMethodBody (MethodDefinition method)
{
if (!method.HasBody)
diff --git a/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs b/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs
index 35c1d13ffea..55114991ccb 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/OutputStep.cs
@@ -26,6 +26,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.IO;
using Mono.Cecil;
@@ -58,6 +59,8 @@ namespace Mono.Linker.Steps {
CopyConfigFileIfNeeded (assembly, directory);
+ Console.WriteLine ("Output {0} : {1}", assembly, Annotations.GetAction (assembly));
+
switch (Annotations.GetAction (assembly)) {
case AssemblyAction.Link:
SaveSymbols (assembly);
@@ -66,6 +69,11 @@ namespace Mono.Linker.Steps {
case AssemblyAction.Copy:
CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory);
break;
+ case AssemblyAction.Delete:
+ var target = GetAssemblyFileName (assembly, directory);
+ if (File.Exists (target))
+ File.Delete (target);
+ break;
}
}
@@ -86,6 +94,11 @@ namespace Mono.Linker.Steps {
if (!File.Exists (config))
return;
+ string target = Path.GetFullPath (GetConfigFile (GetAssemblyFileName (assembly, directory)));
+
+ if (config == target)
+ return;
+
File.Copy (config, GetConfigFile (GetAssemblyFileName (assembly, directory)), true);
}
@@ -101,7 +114,11 @@ namespace Mono.Linker.Steps {
static void CopyAssembly (FileInfo fi, string directory)
{
- File.Copy (fi.FullName, Path.Combine (directory, fi.Name), true);
+ string target = Path.GetFullPath (Path.Combine (directory, fi.Name));
+ if (fi.FullName == target)
+ return;
+
+ File.Copy (fi.FullName, target, true);
}
static string GetAssemblyFileName (AssemblyDefinition assembly, string directory)
diff --git a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromAssemblyStep.cs b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromAssemblyStep.cs
index 55dfa7d1b96..5cb5614b2b9 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromAssemblyStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromAssemblyStep.cs
@@ -54,7 +54,7 @@ namespace Mono.Linker.Steps {
}
}
- static void ProcessLibrary (AssemblyDefinition assembly)
+ public static void ProcessLibrary (AssemblyDefinition assembly)
{
Annotations.SetAction (assembly, AssemblyAction.Copy);
diff --git a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs
index 6a749341508..ee16fa18b69 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/ResolveFromXmlStep.cs
@@ -264,7 +264,7 @@ namespace Mono.Linker.Steps {
MarkMethod (type, meth, signature);
}
- private void MarkMethod (TypeDefinition type, MethodDefinition method, string signature)
+ void MarkMethod (TypeDefinition type, MethodDefinition method, string signature)
{
if (method != null) {
Annotations.Mark (method);
diff --git a/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs b/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs
index 9ef6d4db043..736f43de6fb 100644
--- a/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs
+++ b/mcs/tools/linker/Mono.Linker.Steps/SweepStep.cs
@@ -45,6 +45,11 @@ namespace Mono.Linker.Steps {
if (Annotations.GetAction (assembly) != AssemblyAction.Link)
return;
+ if (!IsMarkedAssembly (assembly)) {
+ RemoveAssembly (assembly);
+ return;
+ }
+
foreach (TypeDefinition type in Clone (assembly.MainModule.Types)) {
if (Annotations.IsMarked (type)) {
SweepType (type);
@@ -56,6 +61,37 @@ namespace Mono.Linker.Steps {
}
}
+ static bool IsMarkedAssembly (AssemblyDefinition assembly)
+ {
+ return Annotations.IsMarked (assembly.MainModule);
+ }
+
+ void RemoveAssembly (AssemblyDefinition assembly)
+ {
+ Annotations.SetAction (assembly, AssemblyAction.Delete);
+
+ SweepReferences (assembly);
+ }
+
+ void SweepReferences (AssemblyDefinition target)
+ {
+ foreach (var assembly in Context.GetAssemblies ())
+ SweepReferences (assembly, target);
+ }
+
+ void SweepReferences (AssemblyDefinition assembly, AssemblyDefinition target)
+ {
+ var references = assembly.MainModule.AssemblyReferences;
+ for (int i = 0; i < references.Count; i++) {
+ var reference = references [i];
+ if (reference.FullName != target.Name.FullName)
+ continue;
+
+ references.RemoveAt (i);
+ return;
+ }
+ }
+
static ICollection Clone (ICollection collection)
{
return new ArrayList (collection);
@@ -78,9 +114,11 @@ namespace Mono.Linker.Steps {
static void SweepMemberReferences (ModuleDefinition module, TypeReference reference)
{
- foreach (MemberReference member in Clone (module.MemberReferences)) {
- if (member.DeclaringType == reference)
- module.MemberReferences.Remove (member);
+ var references = module.MemberReferences;
+
+ for (int i = 0; i < references.Count; i++) {
+ if (references [i].DeclaringType == reference)
+ references.RemoveAt (i--);
}
}
@@ -95,16 +133,21 @@ namespace Mono.Linker.Steps {
static void SweepType (TypeDefinition type)
{
- SweepCollection (type.Fields);
- SweepCollection (type.Constructors);
- SweepCollection (type.Methods);
+ if (type.HasFields)
+ SweepCollection (type.Fields);
+
+ if (type.HasConstructors)
+ SweepCollection (type.Constructors);
+
+ if (type.HasMethods)
+ SweepCollection (type.Methods);
}
static void SweepCollection (IList list)
{
- foreach (IAnnotationProvider provider in Clone (list))
- if (!Annotations.IsMarked (provider))
- list.Remove (provider);
+ for (int i = 0; i < list.Count; i++)
+ if (!Annotations.IsMarked ((IAnnotationProvider) list [i]))
+ list.RemoveAt (i--);
}
}
}
diff --git a/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs b/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs
new file mode 100644
index 00000000000..f92b242bda6
--- /dev/null
+++ b/mcs/tools/linker/Mono.Linker.Steps/TypeMapStep.cs
@@ -0,0 +1,240 @@
+//
+// TypeMapStep.cs
+//
+// Author:
+// Jb Evain (jbevain@novell.com)
+//
+// (C) 2009 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+
+using Mono.Cecil;
+
+namespace Mono.Linker.Steps {
+
+ public class TypeMapStep : BaseStep {
+
+ protected override void ProcessAssembly (AssemblyDefinition assembly)
+ {
+ foreach (TypeDefinition type in assembly.MainModule.Types)
+ MapType (type);
+ }
+
+ static void MapType (TypeDefinition type)
+ {
+ MapVirtualMethods (type);
+ }
+
+ static void MapVirtualMethods (TypeDefinition type)
+ {
+ if (!type.HasMethods)
+ return;
+
+ foreach (MethodDefinition method in type.Methods) {
+ if (!method.IsVirtual)
+ continue;
+
+ MapVirtualMethod (method);
+
+ if (method.HasOverrides)
+ MapOverrides (method);
+ }
+ }
+
+ static void MapVirtualMethod (MethodDefinition method)
+ {
+ MapVirtualBaseMethod (method);
+ MapVirtualInterfaceMethod (method);
+ }
+
+ static void MapVirtualBaseMethod (MethodDefinition method)
+ {
+ MethodDefinition @base = GetBaseMethodInTypeHierarchy (method);
+ if (@base == null)
+ return;
+
+ AnnotateMethods (@base, method);
+ }
+
+ static void MapVirtualInterfaceMethod (MethodDefinition method)
+ {
+ MethodDefinition @base = GetBaseMethodInInterfaceHierarchy (method);
+ if (@base == null)
+ return;
+
+ AnnotateMethods (@base, method);
+ }
+
+ static void MapOverrides (MethodDefinition method)
+ {
+ foreach (MethodReference override_ref in method.Overrides) {
+ MethodDefinition @override = override_ref.Resolve ();
+ if (@override == null)
+ continue;
+
+ AnnotateMethods (@override, method);
+ }
+ }
+
+ static void AnnotateMethods (MethodDefinition @base, MethodDefinition @override)
+ {
+ Annotations.AddBaseMethod (@override, @base);
+ Annotations.AddOverride (@base, @override);
+ }
+
+ static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method)
+ {
+ TypeDefinition @base = GetBaseType (method.DeclaringType);
+ while (@base != null) {
+ MethodDefinition base_method = TryMatchMethod (@base, method);
+ if (base_method != null)
+ return base_method;
+
+ @base = GetBaseType (@base);
+ }
+
+ return null;
+ }
+
+ static MethodDefinition GetBaseMethodInInterfaceHierarchy (MethodDefinition method)
+ {
+ return GetBaseMethodInInterfaceHierarchy (method.DeclaringType, method);
+ }
+
+ static MethodDefinition GetBaseMethodInInterfaceHierarchy (TypeDefinition type, MethodDefinition method)
+ {
+ if (!type.HasInterfaces)
+ return null;
+
+ foreach (TypeReference interface_ref in type.Interfaces) {
+ TypeDefinition @interface = interface_ref.Resolve ();
+ if (@interface == null)
+ continue;
+
+ MethodDefinition base_method = TryMatchMethod (@interface, method);
+ if (base_method != null)
+ return base_method;
+
+ base_method = GetBaseMethodInInterfaceHierarchy (@interface, method);
+ if (base_method != null)
+ return base_method;
+ }
+
+ return null;
+ }
+
+ static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method)
+ {
+ if (!type.HasMethods)
+ return null;
+
+ foreach (MethodDefinition candidate in type.Methods)
+ if (MethodMatch (candidate, method))
+ return candidate;
+
+ return null;
+ }
+
+ static bool MethodMatch (MethodDefinition candidate, MethodDefinition method)
+ {
+ if (!candidate.IsVirtual)
+ return false;
+
+ if (candidate.Name != method.Name)
+ return false;
+
+ if (!TypeMatch (candidate.ReturnType.ReturnType, method.ReturnType.ReturnType))
+ return false;
+
+ if (candidate.Parameters.Count != method.Parameters.Count)
+ return false;
+
+ for (int i = 0; i < candidate.Parameters.Count; i++)
+ if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType))
+ return false;
+
+ return true;
+ }
+
+ static bool TypeMatch (ModType a, ModType b)
+ {
+ if (!TypeMatch (a.ModifierType, b.ModifierType))
+ return false;
+
+ return TypeMatch (a.ElementType, b.ElementType);
+ }
+
+ static bool TypeMatch (TypeSpecification a, TypeSpecification b)
+ {
+ if (a is GenericInstanceType)
+ return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b);
+
+ if (a is ModType)
+ return TypeMatch ((ModType) a, (ModType) b);
+
+ return TypeMatch (a.ElementType, b.ElementType);
+ }
+
+ static bool TypeMatch (GenericInstanceType a, GenericInstanceType b)
+ {
+ if (!TypeMatch (a.ElementType, b.ElementType))
+ return false;
+
+ if (a.GenericArguments.Count != b.GenericArguments.Count)
+ return false;
+
+ if (a.GenericArguments.Count == 0)
+ return true;
+
+ for (int i = 0; i < a.GenericArguments.Count; i++)
+ if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i]))
+ return false;
+
+ return true;
+ }
+
+ static bool TypeMatch (TypeReference a, TypeReference b)
+ {
+ if (a is GenericParameter)
+ return true;
+
+ if (a is TypeSpecification || b is TypeSpecification) {
+ if (a.GetType () != b.GetType ())
+ return false;
+
+ return TypeMatch ((TypeSpecification) a, (TypeSpecification) b);
+ }
+
+ return a.FullName == b.FullName;
+ }
+
+ static TypeDefinition GetBaseType (TypeDefinition type)
+ {
+ if (type == null || type.BaseType == null)
+ return null;
+
+ return type.BaseType.Resolve ();
+ }
+ }
+}
diff --git a/mcs/tools/linker/Mono.Linker/Annotations.cs b/mcs/tools/linker/Mono.Linker/Annotations.cs
index 635e174c2a4..55330d3e276 100644
--- a/mcs/tools/linker/Mono.Linker/Annotations.cs
+++ b/mcs/tools/linker/Mono.Linker/Annotations.cs
@@ -26,6 +26,9 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
+using System.Collections;
+
using Mono.Cecil;
namespace Mono.Linker {
@@ -36,8 +39,11 @@ namespace Mono.Linker {
private static readonly object _markedKey = new object ();
private static readonly object _processedKey = new object ();
private static readonly object _preservedKey = new object ();
+ private static readonly object _preservedMethodsKey = new object ();
private static readonly object _publicKey = new object ();
private static readonly object _symbolsKey = new object ();
+ private static readonly object _overrideKey = new object ();
+ private static readonly object _baseKey = new object ();
public static AssemblyAction GetAction (AssemblyDefinition assembly)
{
@@ -46,7 +52,8 @@ namespace Mono.Linker {
public static MethodAction GetAction (MethodDefinition method)
{
- return (MethodAction) GetAction (AsProvider (method));
+ var action = GetAction (AsProvider (method));
+ return action == null ? MethodAction.Nothing : (MethodAction) action;
}
static object GetAction (IAnnotationProvider provider)
@@ -134,6 +141,54 @@ namespace Mono.Linker {
AsProvider (assembly).Annotations [_symbolsKey] = _symbolsKey;
}
+ public static void AddOverride (MethodDefinition @base, MethodDefinition @override)
+ {
+ ArrayList methods = (ArrayList) GetOverrides (@base);
+ if (methods == null) {
+ methods = new ArrayList ();
+ AsProvider (@base).Annotations.Add (_overrideKey, methods);
+ }
+
+ methods.Add (@override);
+ }
+
+ public static IList GetOverrides (MethodDefinition method)
+ {
+ return (IList) AsProvider (method).Annotations [_overrideKey];
+ }
+
+ public static void AddBaseMethod (MethodDefinition method, MethodDefinition @base)
+ {
+ ArrayList methods = (ArrayList) GetBaseMethods (method);
+ if (methods == null) {
+ methods = new ArrayList ();
+ AsProvider (method).Annotations.Add (_baseKey, methods);
+ }
+
+ methods.Add (@base);
+ }
+
+ public static IList GetBaseMethods (MethodDefinition method)
+ {
+ return (IList) AsProvider (method).Annotations [_baseKey];
+ }
+
+ public static IList GetPreservedMethods (TypeDefinition type)
+ {
+ return (IList) AsProvider (type).Annotations [_preservedMethodsKey];
+ }
+
+ public static void AddPreservedMethod (TypeDefinition type, MethodDefinition method)
+ {
+ ArrayList methods = (ArrayList) GetPreservedMethods (type);
+ if (methods == null) {
+ methods = new ArrayList ();
+ AsProvider (type).Annotations.Add (_preservedMethodsKey, methods);
+ }
+
+ methods.Add (method);
+ }
+
private Annotations ()
{
}
diff --git a/mcs/tools/linker/Mono.Linker/AssemblyAction.cs b/mcs/tools/linker/Mono.Linker/AssemblyAction.cs
index 9d675f23e4a..8eac19e5e48 100644
--- a/mcs/tools/linker/Mono.Linker/AssemblyAction.cs
+++ b/mcs/tools/linker/Mono.Linker/AssemblyAction.cs
@@ -31,6 +31,7 @@ namespace Mono.Linker {
public enum AssemblyAction {
Skip,
Copy,
- Link
+ Link,
+ Delete,
}
}
diff --git a/mcs/tools/linker/Mono.Linker/Driver.cs b/mcs/tools/linker/Mono.Linker/Driver.cs
index eb99a9fcd96..7d1963cc3db 100644
--- a/mcs/tools/linker/Mono.Linker/Driver.cs
+++ b/mcs/tools/linker/Mono.Linker/Driver.cs
@@ -163,7 +163,7 @@ namespace Mono.Linker {
foreach (string custom_step in custom_steps)
AddCustomStep (p, custom_step);
-
+
p.AddStepAfter (typeof (LoadReferencesStep), new LoadI18nAssemblies (assemblies));
p.Process (context);
@@ -310,6 +310,7 @@ namespace Mono.Linker {
Pipeline p = new Pipeline ();
p.AppendStep (new LoadReferencesStep ());
p.AppendStep (new BlacklistStep ());
+ p.AppendStep (new TypeMapStep ());
p.AppendStep (new MarkStep ());
p.AppendStep (new SweepStep ());
p.AppendStep (new CleanStep ());
diff --git a/mcs/tools/linker/Mono.Linker/Pipeline.cs b/mcs/tools/linker/Mono.Linker/Pipeline.cs
index f528ddf46a2..7c2b120d4ec 100644
--- a/mcs/tools/linker/Mono.Linker/Pipeline.cs
+++ b/mcs/tools/linker/Mono.Linker/Pipeline.cs
@@ -61,7 +61,7 @@ namespace Mono.Linker {
}
}
}
-
+
public void ReplaceStep (Type target, IStep step)
{
AddStepBefore (target, step);
@@ -96,6 +96,7 @@ namespace Mono.Linker {
{
while (_steps.Count > 0) {
IStep step = (IStep) _steps [0];
+ Console.WriteLine ("Processing {0}", step.GetType ());
step.Process (context);
_steps.Remove (step);
}
diff --git a/mcs/tools/linker/monolinker.exe.sources b/mcs/tools/linker/monolinker.exe.sources
index 24b25f13d1e..588cf4ae490 100644
--- a/mcs/tools/linker/monolinker.exe.sources
+++ b/mcs/tools/linker/monolinker.exe.sources
@@ -24,4 +24,5 @@
./Mono.Linker.Steps/MarkStep.cs
./Mono.Linker.Steps/BlacklistStep.cs
./Mono.Linker.Steps/OutputStep.cs
+./Mono.Linker.Steps/TypeMapStep.cs
./Mono.Linker.Steps/IStep.cs