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 + +