diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.targets b/src/BuildIntegration/Microsoft.NETCore.Native.targets
index c5ce3bbddf2..61a46edf9da 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -189,6 +189,8 @@ See the LICENSE file in the project root for more information.
+
+
diff --git a/src/Common/src/System/CommonRuntimeTypes.cs b/src/Common/src/System/CommonRuntimeTypes.cs
index 435a1867eb9..7826a1ca95d 100644
--- a/src/Common/src/System/CommonRuntimeTypes.cs
+++ b/src/Common/src/System/CommonRuntimeTypes.cs
@@ -10,58 +10,40 @@ namespace System
//
internal static class CommonRuntimeTypes
{
- internal static Type Object { get { return s_object; } }
- internal static Type ValueType { get { return s_valuetype; } }
- internal static Type Type { get { return s_type; } }
- internal static Type Attribute { get { return s_attribute; } }
- internal static Type String { get { return s_string; } }
- internal static Type Array { get { return s_array; } }
- internal static Type Enum { get { return s_enum; } }
- internal static Type Boolean { get { return s_boolean; } }
- internal static Type Char { get { return s_char; } }
- internal static Type Byte { get { return s_byte; } }
- internal static Type SByte { get { return s_sByte; } }
- internal static Type UInt16 { get { return s_uInt16; } }
- internal static Type Int16 { get { return s_int16; } }
- internal static Type UInt32 { get { return s_uInt32; } }
- internal static Type Int32 { get { return s_int32; } }
- internal static Type UInt64 { get { return s_uInt64; } }
- internal static Type Int64 { get { return s_int64; } }
- internal static Type UIntPtr { get { return s_uIntPtr; } }
- internal static Type IntPtr { get { return s_intPtr; } }
- internal static Type Single { get { return s_single; } }
- internal static Type Double { get { return s_double; } }
- internal static Type Decimal { get { return s_decimal; } }
- internal static Type DateTime { get { return s_datetime; } }
- internal static Type Nullable { get { return s_nullable; } }
- internal static Type Void { get { return s_void; } }
- internal static Type MulticastDelegate { get { return s_multicastDelegate; } }
+ internal static Type Object { get; } = typeof(object);
+ internal static Type ValueType { get; } = typeof(ValueType);
+ internal static Type Type { get; } = typeof(Type);
+ internal static Type Attribute { get; } = typeof(Attribute);
+ internal static Type String { get; } = typeof(string);
+ internal static Type Array { get; } = typeof(Array);
+ internal static Type Enum { get; } = typeof(Enum);
+ internal static Type Boolean { get; } = typeof(bool);
+ internal static Type Char { get; } = typeof(char);
+ internal static Type Byte { get; } = typeof(byte);
+ internal static Type SByte { get; } = typeof(sbyte);
+ internal static Type UInt16 { get; } = typeof(ushort);
+ internal static Type Int16 { get; } = typeof(short);
+ internal static Type UInt32 { get; } = typeof(uint);
+ internal static Type Int32 { get; } = typeof(int);
+ internal static Type UInt64 { get; } = typeof(ulong);
+ internal static Type Int64 { get; } = typeof(long);
+ internal static Type UIntPtr { get; } = typeof(UIntPtr);
+ internal static Type IntPtr { get; } = typeof(IntPtr);
+ internal static Type Single { get; } = typeof(float);
+ internal static Type Double { get; } = typeof(double);
+ internal static Type Decimal { get { return NotSoCommonTypes.s_decimal; } }
+ internal static Type DateTime { get { return NotSoCommonTypes.s_datetime; } }
+ internal static Type Nullable { get; } = typeof(Nullable<>);
+ internal static Type Void { get; } = typeof(void);
+ internal static Type MulticastDelegate { get; } = typeof(MulticastDelegate);
- private static Type s_object = typeof(object);
- private static Type s_valuetype = typeof(ValueType);
- private static Type s_type = typeof(Type);
- private static Type s_attribute = typeof(Attribute);
- private static Type s_string = typeof(string);
- private static Type s_array = typeof(Array);
- private static Type s_enum = typeof(Enum);
- private static Type s_boolean = typeof(bool);
- private static Type s_char = typeof(char);
- private static Type s_byte = typeof(byte);
- private static Type s_sByte = typeof(sbyte);
- private static Type s_uInt16 = typeof(ushort);
- private static Type s_int16 = typeof(short);
- private static Type s_uInt32 = typeof(uint);
- private static Type s_int32 = typeof(int);
- private static Type s_uInt64 = typeof(ulong);
- private static Type s_int64 = typeof(long);
- private static Type s_uIntPtr = typeof(UIntPtr);
- private static Type s_intPtr = typeof(IntPtr);
- private static Type s_single = typeof(float);
- private static Type s_double = typeof(double);
- private static Type s_decimal = typeof(decimal);
- private static Type s_datetime = typeof(DateTime);
- private static Type s_nullable = typeof(Nullable<>);
- private static Type s_void = typeof(void);
- private static Type s_multicastDelegate = typeof(MulticastDelegate);
+ // Following types are not so common and their ToString and formatting is particularly heavy.
+ // Make it less likely that they'll get included in small projects by placing them into
+ // a separate class constructor.
+ private static class NotSoCommonTypes
+ {
+ internal static Type s_decimal = typeof(decimal);
+ internal static Type s_datetime = typeof(DateTime);
+ }
}
}
diff --git a/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.cs b/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.cs
new file mode 100644
index 00000000000..b7622b8e961
--- /dev/null
+++ b/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.cs
@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Xml.Linq;
+using System.Linq;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Reflection;
+
+// This is a simple command line tool to inspect DGML files generated by
+// ILCompiler.DependencyAnalysisFramework's DgmlWriter class.
+//
+// It works best if FirstMarkLogStrategy is used. It might hit cycles if full
+// marking strategy is used, so better not try that. That's untested.
+//
+// Given the name of the DGML file and a name of the node in the DGML graph,
+// it prints the path from the node to the roots.
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ if (args.Length != 2)
+ {
+ Console.WriteLine("Usage:");
+ Console.Write(Assembly.GetExecutingAssembly().ManifestModule.Name);
+ Console.WriteLine(" dgmlfile.xml node_name");
+ return;
+ }
+
+ string file = args[0];
+
+ var directedGraph = XElement.Load(file);
+
+ var idToNode = new Dictionary();
+ var nameToNode = new Dictionary(StringComparer.Ordinal);
+ var nodes = directedGraph.Elements().Single(e => e.Name.LocalName == "Nodes");
+ foreach (var node in nodes.Elements())
+ {
+ Debug.Assert(node.Name.LocalName == "Node");
+ int id = int.Parse(node.Attribute("Id").Value);
+ string name = node.Attribute("Label").Value;
+ var n = new Node(name);
+ idToNode[id] = n;
+ nameToNode[name] = n;
+ }
+
+ var links = directedGraph.Elements().Single(e => e.Name.LocalName == "Links");
+ foreach (var link in links.Elements())
+ {
+ int source = int.Parse(link.Attribute("Source").Value);
+ int target = int.Parse(link.Attribute("Target").Value);
+ string reason = link.Attribute("Reason").Value;
+ idToNode[target].Edges.Add((idToNode[source], reason));
+ }
+
+ string goal = args[1];
+ if (!nameToNode.ContainsKey(goal))
+ Console.WriteLine($"No such node: '{goal}'.");
+ else
+ Dump(nameToNode[goal]);
+ }
+
+ static void Dump(Node current, int indent = 0, string reason = "")
+ {
+ Console.WriteLine($"{new string(' ', indent)}({reason}) {current.Name}");
+
+ foreach (var edge in current.Edges)
+ {
+ Dump(edge.Node, indent + 2, edge.Label);
+ }
+ }
+}
+
+class Node
+{
+ public readonly string Name;
+ public readonly List<(Node Node, string Label)> Edges;
+
+ public Node(string name)
+ {
+ Name = name;
+ Edges = new List<(Node, string)>();
+ }
+}
diff --git a/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.csproj b/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.csproj
new file mode 100644
index 00000000000..afa7bad5e79
--- /dev/null
+++ b/src/ILCompiler.DependencyAnalysisFramework/WhyDgml/Why.csproj
@@ -0,0 +1,6 @@
+
+
+ Exe
+ netcoreapp3.1
+
+