{
while (!QueueIsEmpty ()) {
MethodDefinition method = (MethodDefinition) _methods.Dequeue ();
+ Annotations.Push (method);
ProcessMethod (method);
+ Annotations.Pop ();
}
}
if (CheckProcessed (type))
return null;
+ Annotations.Push (type);
+
MarkScope (type.Scope);
MarkType (type.BaseType);
MarkType (type.DeclaringType);
DoAdditionalTypeProcessing (type);
+ Annotations.Pop ();
+
Annotations.Mark (type);
ApplyPreserveInfo (type);
if (reference.DeclaringType is ArrayType)
return null;
+ Annotations.Push (reference);
if (reference.DeclaringType is GenericInstanceType)
MarkType (reference.DeclaringType);
MethodDefinition method = ResolveMethodDefinition (reference);
- if (method == null)
+ if (method == null) {
+ Annotations.Pop ();
throw new ResolutionException (reference);
+ }
if (Annotations.GetAction (method) == MethodAction.Nothing)
Annotations.SetAction (method, MethodAction.Parse);
EnqueueMethod (method);
+
+ Annotations.Pop ();
+
return method;
}
protected override void Process ()
{
CheckOutputDirectory ();
+ Annotations.SaveDependencies ();
}
void CheckOutputDirectory ()
switch (Annotations.GetAction (assembly)) {
case AssemblyAction.Save:
case AssemblyAction.Link:
+ Context.Annotations.AddDependency (assembly);
assembly.Write (GetAssemblyFileName (assembly, directory), SaveSymbols (assembly));
break;
case AssemblyAction.Copy:
+ Context.Annotations.AddDependency (assembly);
CloseSymbols (assembly);
CopyAssembly (GetOriginalAssemblyFileInfo (assembly), directory, Context.LinkSymbols);
break;
switch (assembly.MainModule.Kind) {
case ModuleKind.Dll:
ProcessLibrary (Context, assembly);
- return;
+ break;
default:
ProcessExecutable (assembly);
- return;
+ break;
}
}
{
SetAction (context, assembly, AssemblyAction.Copy);
+ context.Annotations.Push (assembly);
+
foreach (TypeDefinition type in assembly.MainModule.Types)
MarkType (context, type);
+
+ context.Annotations.Pop ();
}
static void MarkType (LinkContext context, TypeDefinition type)
{
context.Annotations.Mark (type);
+ context.Annotations.Push (type);
+
if (type.HasFields)
MarkFields (context, type.Fields);
if (type.HasMethods)
if (type.HasNestedTypes)
foreach (var nested in type.NestedTypes)
MarkType (context, nested);
+
+ context.Annotations.Pop ();
}
void ProcessExecutable (AssemblyDefinition assembly)
{
SetAction (Context, assembly, AssemblyAction.Link);
+ Annotations.Push (assembly);
+
Annotations.Mark (assembly.EntryPoint.DeclaringType);
MarkMethod (Context, assembly.EntryPoint, MethodAction.Parse);
+
+ Annotations.Pop ();
}
static void MarkFields (LinkContext context, ICollection fields)
using System;
using System.Collections;
using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
using Mono.Cecil;
using Mono.Cecil.Cil;
readonly Dictionary<object, Dictionary<IMetadataTokenProvider, object>> custom_annotations = new Dictionary<object, Dictionary<IMetadataTokenProvider, object>> ();
+ readonly Stack<object> dependency_stack = new Stack<object> ();
+ System.Xml.XmlWriter writer;
+ GZipStream zipStream;
+
+ public void PrepareDependenciesDump ()
+ {
+ System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
+ settings.Indent = true;
+ settings.IndentChars = "\t";
+ var depsFile = File.OpenWrite ("linker-dependencies.xml.gz");
+ zipStream = new GZipStream (depsFile, CompressionMode.Compress);
+
+ writer = System.Xml.XmlWriter.Create (zipStream, settings);
+ writer.WriteStartDocument ();
+ writer.WriteStartElement ("dependencies");
+ writer.WriteStartAttribute ("version");
+ writer.WriteString ("1.0");
+ writer.WriteEndAttribute ();
+ }
+
public AssemblyAction GetAction (AssemblyDefinition assembly)
{
AssemblyAction action;
public void Mark (IMetadataTokenProvider provider)
{
marked.Add (provider);
+ AddDependency (provider);
}
public bool IsMarked (IMetadataTokenProvider provider)
custom_annotations.Add (key, slots);
return slots;
}
+
+ public void AddDependency (object o)
+ {
+ if (writer == null)
+ return;
+
+ KeyValuePair<object, object> pair = new KeyValuePair<object, object> (dependency_stack.Count > 0 ? dependency_stack.Peek () : null, o);
+ writer.WriteStartElement ("edge");
+ writer.WriteAttributeString ("b", TokenString (pair.Key));
+ writer.WriteAttributeString ("e", TokenString (pair.Value));
+ writer.WriteEndElement ();
+ }
+
+ public void Push (object o)
+ {
+ if (writer == null)
+ return;
+
+ if (dependency_stack.Count > 0)
+ AddDependency (o);
+ dependency_stack.Push (o);
+ }
+
+ public void Pop ()
+ {
+ if (writer == null)
+ return;
+
+ dependency_stack.Pop ();
+ }
+
+ string TokenString (object o)
+ {
+ if (o == null)
+ return "N:null";
+
+ if (o is IMetadataTokenProvider)
+ return (o as IMetadataTokenProvider).MetadataToken.TokenType + ":" + o;
+
+ return "Other:" + o;
+ }
+
+ public void SaveDependencies ()
+ {
+ if (writer == null)
+ return;
+
+ writer.WriteEndElement ();
+ writer.WriteEndDocument ();
+ writer.Flush ();
+ writer.Close ();
+ zipStream.Close ();
+
+ writer.Dispose ();
+ zipStream.Dispose ();
+ writer = null;
+ zipStream = null;
+ }
}
}
{
while (_steps.Count > 0) {
IStep step = (IStep) _steps [0];
+ context.Annotations.Push (step);
step.Process (context);
+ context.Annotations.Pop ();
_steps.Remove (step);
}
}
void DispatchAssembly (AssemblyDefinition assembly)
{
- foreach (var substep in on_assemblies)
+ foreach (var substep in on_assemblies) {
+ var bs = substep as BaseSubStep;
+ if (bs != null)
+ bs.Annotations.Push (substep);
substep.ProcessAssembly (assembly);
+ if (bs != null)
+ bs.Annotations.Pop ();
+ }
}
void DispatchType (TypeDefinition type)
{
- foreach (var substep in on_types)
+ foreach (var substep in on_types) {
+ var bs = substep as BaseSubStep;
+ if (bs != null)
+ bs.Annotations.Push (substep);
substep.ProcessType (type);
+ if (bs != null)
+ bs.Annotations.Pop ();
+ }
}
void DispatchField (FieldDefinition field)