Imported Upstream version 5.10.0.69

Former-commit-id: fc39669a0b707dd3c063977486506b6793da2890
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-29 19:03:06 +00:00
parent d8f8abd549
commit e2950ec768
6283 changed files with 453847 additions and 91879 deletions

View File

@@ -0,0 +1,149 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Compiler.Tests", "tests\ILCompiler.Compiler.Tests.csproj", "{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Compiler", "src\ILCompiler.Compiler.csproj", "{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem", "..\ILCompiler.TypeSystem\src\ILCompiler.TypeSystem.csproj", "{846B4638-43AE-452F-B171-D8DB600F1284}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILCompiler.Compiler.Tests.Assets", "tests\ILCompiler.Compiler.Tests.Assets\ILCompiler.Compiler.Tests.Assets.csproj", "{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.CoreLib", "..\Test.CoreLib\src\Test.CoreLib.csproj", "{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|arm = Debug|arm
Debug|arm64 = Debug|arm64
Debug|armel = Debug|armel
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|arm = Release|arm
Release|arm64 = Release|arm64
Release|armel = Release|armel
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|Any CPU.ActiveCfg = Debug|x86
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm.ActiveCfg = Debug|arm
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm.Build.0 = Debug|arm
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm64.ActiveCfg = Debug|arm64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|arm64.Build.0 = Debug|arm64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|armel.ActiveCfg = Debug|armel
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|armel.Build.0 = Debug|armel
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x64.ActiveCfg = Debug|x64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x64.Build.0 = Debug|x64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x86.ActiveCfg = Debug|x86
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Debug|x86.Build.0 = Debug|x86
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|Any CPU.ActiveCfg = Release|x86
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm.ActiveCfg = Release|arm
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm.Build.0 = Release|arm
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm64.ActiveCfg = Release|arm64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|arm64.Build.0 = Release|arm64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|armel.ActiveCfg = Release|armel
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|armel.Build.0 = Release|armel
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x64.ActiveCfg = Release|x64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x64.Build.0 = Release|x64
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x86.ActiveCfg = Release|x86
{A0BB7B15-1E33-4F22-9A2E-6899E6FC669B}.Release|x86.Build.0 = Release|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|Any CPU.ActiveCfg = Debug|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm.ActiveCfg = Debug|arm
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm.Build.0 = Debug|arm
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm64.ActiveCfg = Debug|arm64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|arm64.Build.0 = Debug|arm64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|armel.ActiveCfg = Debug|armel
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|armel.Build.0 = Debug|armel
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x64.ActiveCfg = Debug|x64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x64.Build.0 = Debug|x64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x86.ActiveCfg = Debug|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Debug|x86.Build.0 = Debug|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|Any CPU.ActiveCfg = Release|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm.ActiveCfg = Release|arm
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm.Build.0 = Release|arm
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm64.ActiveCfg = Release|arm64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|arm64.Build.0 = Release|arm64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|armel.ActiveCfg = Release|armel
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|armel.Build.0 = Release|armel
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x64.ActiveCfg = Release|x64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x64.Build.0 = Release|x64
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x86.ActiveCfg = Release|x86
{395E8F7D-52A1-4E69-A4F5-40D94FB6A81B}.Release|x86.Build.0 = Release|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|Any CPU.ActiveCfg = Debug|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm.ActiveCfg = Debug|arm
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm.Build.0 = Debug|arm
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm64.ActiveCfg = Debug|arm64
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|arm64.Build.0 = Debug|arm64
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|armel.ActiveCfg = Debug|armel
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|armel.Build.0 = Debug|armel
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x64.ActiveCfg = Debug|x64
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x64.Build.0 = Debug|x64
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x86.ActiveCfg = Debug|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Debug|x86.Build.0 = Debug|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|Any CPU.ActiveCfg = Release|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm.ActiveCfg = Release|arm
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm.Build.0 = Release|arm
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm64.ActiveCfg = Release|arm64
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|arm64.Build.0 = Release|arm64
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|armel.ActiveCfg = Release|armel
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|armel.Build.0 = Release|armel
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x64.ActiveCfg = Release|x64
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x64.Build.0 = Release|x64
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x86.ActiveCfg = Release|x86
{846B4638-43AE-452F-B171-D8DB600F1284}.Release|x86.Build.0 = Release|x86
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm64.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|arm64.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|armel.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|armel.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x64.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x64.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x86.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Debug|x86.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|Any CPU.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|Any CPU.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm64.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|arm64.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|armel.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|armel.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x64.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x64.Build.0 = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x86.ActiveCfg = Debug|Any CPU
{94D3F829-6ACA-4399-B6CF-EE0486E1E36A}.Release|x86.Build.0 = Debug|Any CPU
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|Any CPU.ActiveCfg = Debug|x86
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm.ActiveCfg = Debug|arm
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm.Build.0 = Debug|arm
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm64.ActiveCfg = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|arm64.Build.0 = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|armel.ActiveCfg = Debug|armel
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|armel.Build.0 = Debug|armel
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x64.ActiveCfg = Debug|x64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x64.Build.0 = Debug|x64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x86.ActiveCfg = Debug|x86
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Debug|x86.Build.0 = Debug|x86
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|Any CPU.ActiveCfg = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|Any CPU.Build.0 = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm.ActiveCfg = Debug|arm
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm.Build.0 = Debug|arm
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm64.ActiveCfg = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|arm64.Build.0 = Debug|arm64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|armel.ActiveCfg = Debug|armel
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|armel.Build.0 = Debug|armel
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x64.ActiveCfg = Debug|x64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x64.Build.0 = Debug|x64
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x86.ActiveCfg = Debug|x86
{22C898F5-CE3A-4BE4-87B0-1E2F29ECB5D6}.Release|x86.Build.0 = Debug|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,263 @@
// 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.Collections.Generic;
using Internal.TypeSystem;
using ILCompiler.Metadata;
using ILCompiler.DependencyAnalysis;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler
{
/// <summary>
/// A metadata manager that knows the full set of metadata ahead of time.
/// </summary>
public sealed class AnalysisBasedMetadataManager : GeneratingMetadataManager, ICompilationRootProvider
{
private readonly List<ModuleDesc> _modulesWithMetadata;
private readonly Dictionary<TypeDesc, MetadataCategory> _reflectableTypes = new Dictionary<TypeDesc, MetadataCategory>();
private readonly Dictionary<MethodDesc, MetadataCategory> _reflectableMethods = new Dictionary<MethodDesc, MetadataCategory>();
private readonly Dictionary<FieldDesc, MetadataCategory> _reflectableFields = new Dictionary<FieldDesc, MetadataCategory>();
public AnalysisBasedMetadataManager(
ModuleDesc generatedAssembly,
CompilerTypeSystemContext typeSystemContext,
MetadataBlockingPolicy blockingPolicy,
string logFile,
StackTraceEmissionPolicy stackTracePolicy,
IEnumerable<ModuleDesc> modulesWithMetadata,
IEnumerable<ReflectableEntity<TypeDesc>> reflectableTypes,
IEnumerable<ReflectableEntity<MethodDesc>> reflectableMethods,
IEnumerable<ReflectableEntity<FieldDesc>> reflectableFields)
: base(generatedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy)
{
_modulesWithMetadata = new List<ModuleDesc>(modulesWithMetadata);
foreach (var refType in reflectableTypes)
{
_reflectableTypes.Add(refType.Entity, refType.Category);
}
foreach (var refMethod in reflectableMethods)
{
// Asking for description or runtime mapping for a member without asking
// for the owning type would mean we can't actually satisfy the request.
Debug.Assert((refMethod.Category & MetadataCategory.Description) == 0
|| (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.Description) != 0);
Debug.Assert((refMethod.Category & MetadataCategory.RuntimeMapping) == 0
|| (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
_reflectableMethods.Add(refMethod.Entity, refMethod.Category);
MethodDesc canonMethod = refMethod.Entity.GetCanonMethodTarget(CanonicalFormKind.Specific);
if (refMethod.Entity != canonMethod)
{
if (!_reflectableMethods.TryGetValue(canonMethod, out MetadataCategory category))
category = 0;
_reflectableMethods[canonMethod] = category | refMethod.Category;
}
}
foreach (var refField in reflectableFields)
{
// Asking for description or runtime mapping for a member without asking
// for the owning type would mean we can't actually satisfy the request.
Debug.Assert((refField.Category & MetadataCategory.Description) == 0
|| (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.Description) != 0);
Debug.Assert((refField.Category & MetadataCategory.RuntimeMapping) == 0
|| (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
_reflectableFields.Add(refField.Entity, refField.Category);
}
#if DEBUG
HashSet<ModuleDesc> moduleHash = new HashSet<ModuleDesc>(_modulesWithMetadata);
foreach (var refType in reflectableTypes)
{
// The instantiated types need to agree on the Description bit with the definition.
// GetMetadataCategory relies on that.
Debug.Assert((GetMetadataCategory(refType.Entity.GetTypeDefinition()) & MetadataCategory.Description)
== (GetMetadataCategory(refType.Entity) & MetadataCategory.Description));
Debug.Assert(!(refType.Entity is MetadataType) || moduleHash.Contains(((MetadataType)refType.Entity).Module));
}
foreach (var refMethod in reflectableMethods)
{
// The instantiated methods need to agree on the Description bit with the definition.
// GetMetadataCategory relies on that.
Debug.Assert((GetMetadataCategory(refMethod.Entity.GetTypicalMethodDefinition()) & MetadataCategory.Description)
== (GetMetadataCategory(refMethod.Entity) & MetadataCategory.Description));
}
foreach (var refField in reflectableFields)
{
// The instantiated fields need to agree on the Description bit with the definition.
// GetMetadataCategory relies on that.
Debug.Assert((GetMetadataCategory(refField.Entity.GetTypicalFieldDefinition()) & MetadataCategory.Description)
== (GetMetadataCategory(refField.Entity) & MetadataCategory.Description));
}
#endif
}
public override IEnumerable<ModuleDesc> GetCompilationModulesWithMetadata()
{
return _modulesWithMetadata;
}
protected override void ComputeMetadata(NodeFactory factory,
out byte[] metadataBlob,
out List<MetadataMapping<MetadataType>> typeMappings,
out List<MetadataMapping<MethodDesc>> methodMappings,
out List<MetadataMapping<FieldDesc>> fieldMappings,
out List<MetadataMapping<MethodDesc>> stackTraceMapping)
{
ComputeMetadata(new Policy(_blockingPolicy, this), factory,
out metadataBlob,
out typeMappings,
out methodMappings,
out fieldMappings,
out stackTraceMapping);
}
protected sealed override MetadataCategory GetMetadataCategory(MethodDesc method)
{
if (_reflectableMethods.TryGetValue(method, out MetadataCategory value))
return value;
return 0;
}
protected sealed override MetadataCategory GetMetadataCategory(TypeDesc type)
{
if (_reflectableTypes.TryGetValue(type, out MetadataCategory value))
return value;
return 0;
}
protected sealed override MetadataCategory GetMetadataCategory(FieldDesc field)
{
if (_reflectableFields.TryGetValue(field, out MetadataCategory value))
return value;
return 0;
}
protected override IEnumerable<FieldDesc> GetFieldsWithRuntimeMapping()
{
foreach (var pair in _reflectableFields)
{
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
yield return pair.Key;
}
}
void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
{
// We go over all the types and members that need a runtime artiface present in the
// compiled executable and root it.
const string reason = "Reflection";
foreach (var pair in _reflectableTypes)
{
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
rootProvider.AddCompilationRoot(pair.Key, reason);
}
foreach (var pair in _reflectableMethods)
{
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
{
MethodDesc method = pair.Key;
// We need to root virtual methods as if they were called virtually.
// This will possibly trigger the generation of other overrides too.
if (method.IsVirtual)
rootProvider.RootVirtualMethodForReflection(method, reason);
if (!method.IsAbstract)
rootProvider.AddCompilationRoot(pair.Key, reason);
}
}
foreach (var pair in _reflectableFields)
{
if ((pair.Value & MetadataCategory.RuntimeMapping) != 0)
{
FieldDesc field = pair.Key;
// We only care about static fields at this point. Instance fields don't need
// runtime artifacts generated in the image.
if (field.IsStatic && !field.IsLiteral)
{
if (field.IsThreadStatic)
rootProvider.RootThreadStaticBaseForType(field.OwningType, reason);
else if (field.HasGCStaticBase)
rootProvider.RootGCStaticBaseForType(field.OwningType, reason);
else
rootProvider.RootNonGCStaticBaseForType(field.OwningType, reason);
}
}
}
}
private struct Policy : IMetadataPolicy
{
private readonly MetadataBlockingPolicy _blockingPolicy;
private readonly ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin;
private readonly AnalysisBasedMetadataManager _parent;
public Policy(MetadataBlockingPolicy blockingPolicy,
AnalysisBasedMetadataManager parent)
{
_blockingPolicy = blockingPolicy;
_parent = parent;
_explicitScopeMixin = new ExplicitScopeAssemblyPolicyMixin();
}
public bool GeneratesMetadata(FieldDesc fieldDef)
{
return (_parent.GetMetadataCategory(fieldDef) & MetadataCategory.Description) != 0;
}
public bool GeneratesMetadata(MethodDesc methodDef)
{
return (_parent.GetMetadataCategory(methodDef) & MetadataCategory.Description) != 0;
}
public bool GeneratesMetadata(MetadataType typeDef)
{
return (_parent.GetMetadataCategory(typeDef) & MetadataCategory.Description) != 0;
}
public bool IsBlocked(MetadataType typeDef)
{
return _blockingPolicy.IsBlocked(typeDef);
}
public bool IsBlocked(MethodDesc methodDef)
{
return _blockingPolicy.IsBlocked(methodDef);
}
public ModuleDesc GetModuleOfType(MetadataType typeDef)
{
return _explicitScopeMixin.GetModuleOfType(typeDef);
}
}
}
public struct ReflectableEntity<TEntity>
{
public readonly TEntity Entity;
public readonly MetadataCategory Category;
public ReflectableEntity(TEntity entity, MetadataCategory category)
{
Entity = entity;
Category = category;
}
}
}

View File

@@ -19,14 +19,21 @@ namespace ILCompiler
/// </summary>
public sealed class BlockedInternalsBlockingPolicy : MetadataBlockingPolicy
{
private enum ModuleBlockingMode
{
None,
BlockedInternals,
FullyBlocked,
}
private class ModuleBlockingState
{
public ModuleDesc Module { get; }
public bool HasBlockedInternals { get; }
public ModuleBlockingState(ModuleDesc module, bool hasBlockedInternals)
public ModuleBlockingMode BlockingMode { get; }
public ModuleBlockingState(ModuleDesc module, ModuleBlockingMode mode)
{
Module = module;
HasBlockedInternals = hasBlockedInternals;
BlockingMode = mode;
}
}
@@ -38,8 +45,18 @@ namespace ILCompiler
protected override bool CompareValueToValue(ModuleBlockingState value1, ModuleBlockingState value2) => Object.ReferenceEquals(value1.Module, value2.Module);
protected override ModuleBlockingState CreateValueFromKey(ModuleDesc module)
{
bool moduleHasBlockingPolicy = module.GetType("System.Runtime.CompilerServices", "__BlockReflectionAttribute", false) != null;
return new ModuleBlockingState(module, moduleHasBlockingPolicy);
ModuleBlockingMode blockingMode = ModuleBlockingMode.None;
if (module.GetType("System.Runtime.CompilerServices", "__BlockAllReflectionAttribute", false) != null)
{
blockingMode = ModuleBlockingMode.FullyBlocked;
}
else if (module.GetType("System.Runtime.CompilerServices", "__BlockReflectionAttribute", false) != null)
{
blockingMode = ModuleBlockingMode.BlockedInternals;
}
return new ModuleBlockingState(module, blockingMode);
}
}
private BlockedModulesHashtable _blockedModules = new BlockedModulesHashtable();
@@ -70,17 +87,17 @@ namespace ILCompiler
protected override bool CompareValueToValue(BlockingState value1, BlockingState value2) => Object.ReferenceEquals(value1.Type, value2.Type);
protected override BlockingState CreateValueFromKey(EcmaType type)
{
bool isBlocked = false;
if (_blockedModules.GetOrCreateValue(type.EcmaModule).HasBlockedInternals)
{
isBlocked = ComputeIsBlocked(type);
}
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(type.EcmaModule).BlockingMode;
bool isBlocked = ComputeIsBlocked(type, moduleBlockingMode);
return new BlockingState(type, isBlocked);
}
private bool ComputeIsBlocked(EcmaType type)
private bool ComputeIsBlocked(EcmaType type, ModuleBlockingMode blockingMode)
{
// If no blocking is applied to the module, the type is not blocked
if (blockingMode == ModuleBlockingMode.None)
return false;
// <Module> type always gets metadata
if (type.IsModuleType)
return false;
@@ -89,6 +106,10 @@ namespace ILCompiler
if (type.Name == "SR")
return false;
// We block everything else if the module is blocked
if (blockingMode == ModuleBlockingMode.FullyBlocked)
return true;
var typeDefinition = type.MetadataReader.GetTypeDefinition(type.Handle);
DefType containingType = type.ContainingType;
if (containingType == null)
@@ -102,7 +123,7 @@ namespace ILCompiler
{
if ((typeDefinition.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic)
{
return ComputeIsBlocked((EcmaType)containingType);
return ComputeIsBlocked((EcmaType)containingType, blockingMode);
}
else
{
@@ -115,6 +136,21 @@ namespace ILCompiler
}
private BlockedTypeHashtable _blockedTypes;
private MetadataType _arrayOfTType;
private MetadataType InitializeArrayOfTType(TypeSystemEntity contextEntity)
{
_arrayOfTType = contextEntity.Context.SystemModule.GetType("System", "Array`1");
return _arrayOfTType;
}
private MetadataType GetArrayOfTType(TypeSystemEntity contextEntity)
{
if (_arrayOfTType != null)
{
return _arrayOfTType;
}
return InitializeArrayOfTType(contextEntity);
}
public BlockedInternalsBlockingPolicy()
{
_blockedTypes = new BlockedTypeHashtable(_blockedModules);
@@ -139,14 +175,28 @@ namespace ILCompiler
if (ecmaMethod == null)
return true;
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(ecmaMethod.Module).BlockingMode;
if (moduleBlockingMode == ModuleBlockingMode.None)
return false;
else if (moduleBlockingMode == ModuleBlockingMode.FullyBlocked)
return true;
// We are blocking internal implementation details
Debug.Assert(moduleBlockingMode == ModuleBlockingMode.BlockedInternals);
if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaMethod.OwningType).IsBlocked)
return true;
if (_blockedModules.GetOrCreateValue(ecmaMethod.Module).HasBlockedInternals)
{
if ((ecmaMethod.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
return true;
}
if ((ecmaMethod.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
return true;
// Methods on Array`1<T> are implementation details that implement the generic interfaces on
// arrays. They should not generate metadata or be reflection invokable.
// We could get rid of this special casing two ways:
// * Make these method stop being regular EcmaMethods with Array<T> as their owning type, or
// * Make these methods implement the interfaces explicitly (they would become private and naturally blocked)
if (ecmaMethod.OwningType == GetArrayOfTType(ecmaMethod))
return true;
return false;
}
@@ -159,14 +209,20 @@ namespace ILCompiler
if (ecmaField == null)
return true;
ModuleBlockingMode moduleBlockingMode = _blockedModules.GetOrCreateValue(ecmaField.Module).BlockingMode;
if (moduleBlockingMode == ModuleBlockingMode.None)
return false;
else if (moduleBlockingMode == ModuleBlockingMode.FullyBlocked)
return true;
// We are blocking internal implementation details
Debug.Assert(moduleBlockingMode == ModuleBlockingMode.BlockedInternals);
if (_blockedTypes.GetOrCreateValue((EcmaType)ecmaField.OwningType).IsBlocked)
return true;
if (_blockedModules.GetOrCreateValue(ecmaField.Module).HasBlockedInternals)
{
if ((ecmaField.Attributes & FieldAttributes.Public) != FieldAttributes.Public)
return true;
}
if ((ecmaField.Attributes & FieldAttributes.Public) != FieldAttributes.Public)
return true;
return false;
}

View File

@@ -0,0 +1,28 @@
// 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 Internal.TypeSystem;
namespace ILCompiler
{
public class CodeGenerationFailedException : InternalCompilerErrorException
{
private const string MessageText = "Code generation failed";
public MethodDesc Method { get; }
public CodeGenerationFailedException(MethodDesc method)
: this(method, null)
{
}
public CodeGenerationFailedException(MethodDesc method, Exception inner)
: base(MessageText, inner)
{
Method = method;
}
}
}

View File

@@ -0,0 +1,95 @@
// 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 Internal.TypeSystem;
namespace ILCompiler
{
/// <summary>
/// Compilation roots necessary to enable use of the jit intrinsic based Comparer<T>.Default and EqualityComparer<T>.Default implementations
/// </summary>
public class ComparerCompilationRootProvider : ICompilationRootProvider
{
TypeSystemContext _context;
public ComparerCompilationRootProvider(TypeSystemContext context)
{
_context = context;
}
private Instantiation GetUniformInstantiation(int numArgs, TypeDesc uniformInstanitationType)
{
TypeDesc[] args = new TypeDesc[numArgs];
for (int i = 0; i < numArgs; i++)
args[i] = uniformInstanitationType;
return new Instantiation(args);
}
private MethodDesc InstantiateMethodOverUniformType(MethodDesc method, TypeDesc uniformInstanitationType)
{
method = method.GetTypicalMethodDefinition();
Instantiation typeUniformInstantiation = GetUniformInstantiation(method.OwningType.Instantiation.Length, uniformInstanitationType);
DefType owningType;
if (typeUniformInstantiation.Length == 0)
owningType = (DefType)method.OwningType;
else
owningType = ((MetadataType)method.OwningType).MakeInstantiatedType(typeUniformInstantiation);
Instantiation methodUniformInstantiation = GetUniformInstantiation(method.Instantiation.Length, uniformInstanitationType);
MethodDesc uninstantiatedMethod = owningType.FindMethodOnTypeWithMatchingTypicalMethod(method);
if (methodUniformInstantiation.Length == 0)
return uninstantiatedMethod;
else
return uninstantiatedMethod.MakeInstantiatedMethod(methodUniformInstantiation);
}
private void AddUniformInstantiationForMethod(IRootingServiceProvider rootProvider, MethodDesc method, TypeDesc uniformInstanitationType)
{
MethodDesc instantiatedMethod = InstantiateMethodOverUniformType(method, uniformInstanitationType);
rootProvider.AddCompilationRoot(instantiatedMethod, "Adding uniform instantiation");
}
private void AddCanonInstantiationsForMethod(IRootingServiceProvider rootProvider, MethodDesc method, bool normalCanonSupported)
{
if (_context.SupportsCanon && normalCanonSupported)
AddUniformInstantiationForMethod(rootProvider, method, _context.CanonType);
if (_context.SupportsUniversalCanon)
AddUniformInstantiationForMethod(rootProvider, method, _context.UniversalCanonType);
}
private void AddCanonInstantiationsForMethod(IRootingServiceProvider rootProvider, MetadataType type, string methodName, bool normalCanonSupported)
{
MethodDesc method = type.GetMethod(methodName, null);
AddCanonInstantiationsForMethod(rootProvider, method, normalCanonSupported);
}
public void AddCompilationRoots(IRootingServiceProvider rootProvider)
{
ModuleDesc systemModule = ((MetadataType)_context.GetWellKnownType(WellKnownType.Object)).Module;
MetadataType equalityComparerType = systemModule.GetType("Internal.IntrinsicSupport", "EqualityComparerHelpers", false) as MetadataType;
if (equalityComparerType != null)
{
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownGenericEquatableComparer", true);
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownObjectEquatableComparer", true);
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownNullableEquatableComparer", false);
AddCanonInstantiationsForMethod(rootProvider, equalityComparerType, "GetKnownEnumEquatableComparer", false);
}
MetadataType comparerType = systemModule.GetType("Internal.IntrinsicSupport", "ComparerHelpers", false) as MetadataType;
if (comparerType != null)
{
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownGenericComparer", true);
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownObjectComparer", true);
AddCanonInstantiationsForMethod(rootProvider, comparerType, "GetKnownNullableComparer", false);
}
}
}
}

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using ILCompiler.DependencyAnalysis;
@@ -23,6 +24,8 @@ namespace ILCompiler
protected readonly DependencyAnalyzerBase<NodeFactory> _dependencyGraph;
protected readonly NodeFactory _nodeFactory;
protected readonly Logger _logger;
private readonly DebugInformationProvider _debugInformationProvider;
private readonly DevirtualizationManager _devirtualizationManager;
public NameMangler NameMangler => _nodeFactory.NameMangler;
public NodeFactory NodeFactory => _nodeFactory;
@@ -30,8 +33,6 @@ namespace ILCompiler
public Logger Logger => _logger;
internal PInvokeILProvider PInvokeILProvider { get; }
protected abstract bool GenerateDebugInfo { get; }
private readonly TypeGetTypeMethodThunkCache _typeGetTypeMethodThunks;
private readonly AssemblyGetExecutingAssemblyMethodThunkCache _assemblyGetExecutingAssemblyMethodThunks;
private readonly MethodBaseGetCurrentMethodThunkCache _methodBaseGetCurrentMethodThunks;
@@ -40,11 +41,15 @@ namespace ILCompiler
DependencyAnalyzerBase<NodeFactory> dependencyGraph,
NodeFactory nodeFactory,
IEnumerable<ICompilationRootProvider> compilationRoots,
DebugInformationProvider debugInformationProvider,
DevirtualizationManager devirtualizationManager,
Logger logger)
{
_dependencyGraph = dependencyGraph;
_nodeFactory = nodeFactory;
_logger = logger;
_debugInformationProvider = debugInformationProvider;
_devirtualizationManager = devirtualizationManager;
_dependencyGraph.ComputeDependencyRoutine += ComputeDependencyNodeDependencies;
NodeFactory.AttachToDependencyGraph(_dependencyGraph);
@@ -115,12 +120,7 @@ namespace ILCompiler
public MethodDebugInformation GetDebugInfo(MethodIL methodIL)
{
if (!GenerateDebugInfo)
return MethodDebugInformation.None;
// This method looks odd right now, but it's an extensibility point that lets us generate
// fake debugging information for things that don't have physical symbols.
return methodIL.GetDebugInfo();
return _debugInformationProvider.GetDebugInfo(methodIL);
}
/// <summary>
@@ -176,7 +176,142 @@ namespace ILCompiler
return intrinsicMethod;
}
void ICompilation.Compile(string outputFile, ObjectDumper dumper)
public bool HasFixedSlotVTable(TypeDesc type)
{
return NodeFactory.VTable(type).HasFixedSlots;
}
public bool IsEffectivelySealed(TypeDesc type)
{
return _devirtualizationManager.IsEffectivelySealed(type);
}
public bool IsEffectivelySealed(MethodDesc method)
{
return _devirtualizationManager.IsEffectivelySealed(method);
}
public MethodDesc ResolveVirtualMethod(MethodDesc declMethod, TypeDesc implType)
{
return _devirtualizationManager.ResolveVirtualMethod(declMethod, implType);
}
public bool NeedsRuntimeLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
{
switch (lookupKind)
{
case ReadyToRunHelperId.TypeHandle:
case ReadyToRunHelperId.NecessaryTypeHandle:
case ReadyToRunHelperId.DefaultConstructor:
return ((TypeDesc)targetOfLookup).IsRuntimeDeterminedSubtype;
case ReadyToRunHelperId.MethodDictionary:
case ReadyToRunHelperId.MethodEntry:
case ReadyToRunHelperId.VirtualDispatchCell:
case ReadyToRunHelperId.MethodHandle:
return ((MethodDesc)targetOfLookup).IsRuntimeDeterminedExactMethod;
case ReadyToRunHelperId.FieldHandle:
return ((FieldDesc)targetOfLookup).OwningType.IsRuntimeDeterminedSubtype;
default:
throw new NotImplementedException();
}
}
public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object targetOfLookup)
{
switch (lookupKind)
{
case ReadyToRunHelperId.TypeHandle:
return NodeFactory.ConstructedTypeSymbol((TypeDesc)targetOfLookup);
case ReadyToRunHelperId.NecessaryTypeHandle:
return NodeFactory.NecessaryTypeSymbol((TypeDesc)targetOfLookup);
case ReadyToRunHelperId.MethodDictionary:
return NodeFactory.MethodGenericDictionary((MethodDesc)targetOfLookup);
case ReadyToRunHelperId.MethodEntry:
return NodeFactory.FatFunctionPointer((MethodDesc)targetOfLookup);
case ReadyToRunHelperId.MethodHandle:
return NodeFactory.RuntimeMethodHandle((MethodDesc)targetOfLookup);
case ReadyToRunHelperId.FieldHandle:
return NodeFactory.RuntimeFieldHandle((FieldDesc)targetOfLookup);
case ReadyToRunHelperId.DefaultConstructor:
{
var type = (TypeDesc)targetOfLookup;
MethodDesc ctor = type.GetDefaultConstructor();
if (ctor == null)
{
MetadataType activatorType = TypeSystemContext.SystemModule.GetKnownType("System", "Activator");
MetadataType classWithMissingCtor = activatorType.GetKnownNestedType("ClassWithMissingConstructor");
ctor = classWithMissingCtor.GetParameterlessConstructor();
}
return NodeFactory.CanonicalEntrypoint(ctor);
}
default:
throw new NotImplementedException();
}
}
public GenericDictionaryLookup ComputeGenericLookup(MethodDesc contextMethod, ReadyToRunHelperId lookupKind, object targetOfLookup)
{
GenericContextSource contextSource;
if (contextMethod.RequiresInstMethodDescArg())
{
contextSource = GenericContextSource.MethodParameter;
}
else if (contextMethod.RequiresInstMethodTableArg())
{
contextSource = GenericContextSource.TypeParameter;
}
else
{
Debug.Assert(contextMethod.AcquiresInstMethodTableFromThis());
contextSource = GenericContextSource.ThisObject;
}
// Can we do a fixed lookup? Start by checking if we can get to the dictionary.
// Context source having a vtable with fixed slots is a prerequisite.
if (contextSource == GenericContextSource.MethodParameter
|| HasFixedSlotVTable(contextMethod.OwningType))
{
DictionaryLayoutNode dictionaryLayout;
if (contextSource == GenericContextSource.MethodParameter)
dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod);
else
dictionaryLayout = _nodeFactory.GenericDictionaryLayout(contextMethod.OwningType);
// If the dictionary layout has fixed slots, we can compute the lookup now. Otherwise defer to helper.
if (dictionaryLayout.HasFixedSlots)
{
int pointerSize = _nodeFactory.Target.PointerSize;
GenericLookupResult lookup = ReadyToRunGenericHelperNode.GetLookupSignature(_nodeFactory, lookupKind, targetOfLookup);
int dictionarySlot = dictionaryLayout.GetSlotForFixedEntry(lookup);
if (dictionarySlot != -1)
{
int dictionaryOffset = dictionarySlot * pointerSize;
if (contextSource == GenericContextSource.MethodParameter)
{
return GenericDictionaryLookup.CreateFixedLookup(contextSource, dictionaryOffset);
}
else
{
int vtableSlot = VirtualMethodSlotHelper.GetGenericDictionarySlot(_nodeFactory, contextMethod.OwningType);
int vtableOffset = EETypeNode.GetVTableOffset(pointerSize) + vtableSlot * pointerSize;
return GenericDictionaryLookup.CreateFixedLookup(contextSource, vtableOffset, dictionaryOffset);
}
}
}
}
// Fixed lookup not possible - use helper.
return GenericDictionaryLookup.CreateHelperLookup(contextSource);
}
CompilationResults ICompilation.Compile(string outputFile, ObjectDumper dumper)
{
if (dumper != null)
{
@@ -191,15 +326,8 @@ namespace ILCompiler
{
dumper.End();
}
}
void ICompilation.WriteDependencyLog(string fileName)
{
using (FileStream dgmlOutput = new FileStream(fileName, FileMode.Create))
{
DgmlWriter.WriteDependencyGraphToStream(dgmlOutput, _dependencyGraph, _nodeFactory);
dgmlOutput.Flush();
}
return new CompilationResults(_dependencyGraph, _nodeFactory);
}
private class RootingServiceProvider : IRootingServiceProvider
@@ -224,59 +352,130 @@ namespace ILCompiler
public void AddCompilationRoot(TypeDesc type, string reason)
{
if (!ConstructedEETypeNode.CreationAllowed(type))
{
_graph.AddRoot(_factory.NecessaryTypeSymbol(type), reason);
}
else
{
_graph.AddRoot(_factory.ConstructedTypeSymbol(type), reason);
}
_graph.AddRoot(_factory.MaximallyConstructableType(type), reason);
}
public void RootStaticBasesForType(TypeDesc type, string reason)
public void RootThreadStaticBaseForType(TypeDesc type, string reason)
{
Debug.Assert(!type.IsGenericDefinition);
MetadataType metadataType = type as MetadataType;
if (metadataType != null)
if (metadataType != null && metadataType.ThreadStaticFieldSize.AsInt > 0)
{
if (metadataType.ThreadStaticFieldSize.AsInt > 0)
{
_graph.AddRoot(_factory.TypeThreadStaticIndex(metadataType), reason);
}
_graph.AddRoot(_factory.TypeThreadStaticIndex(metadataType), reason);
if (metadataType.GCStaticFieldSize.AsInt > 0)
{
_graph.AddRoot(_factory.TypeGCStaticsSymbol(metadataType), reason);
}
if (metadataType.NonGCStaticFieldSize.AsInt > 0)
{
// Also explicitly root the non-gc base if we have a lazy cctor
if(_factory.TypeSystemContext.HasLazyStaticConstructor(type))
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
}
}
}
public void RootGCStaticBaseForType(TypeDesc type, string reason)
{
Debug.Assert(!type.IsGenericDefinition);
MetadataType metadataType = type as MetadataType;
if (metadataType != null && metadataType.GCStaticFieldSize.AsInt > 0)
{
_graph.AddRoot(_factory.TypeGCStaticsSymbol(metadataType), reason);
// Also explicitly root the non-gc base if we have a lazy cctor
if (_factory.TypeSystemContext.HasLazyStaticConstructor(type))
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
}
}
public void RootNonGCStaticBaseForType(TypeDesc type, string reason)
{
Debug.Assert(!type.IsGenericDefinition);
MetadataType metadataType = type as MetadataType;
if (metadataType != null && (metadataType.NonGCStaticFieldSize.AsInt > 0 || _factory.TypeSystemContext.HasLazyStaticConstructor(type)))
{
_graph.AddRoot(_factory.TypeNonGCStaticsSymbol(metadataType), reason);
}
}
public void RootVirtualMethodForReflection(MethodDesc method, string reason)
{
Debug.Assert(method.IsVirtual);
if (!_factory.CompilationModuleGroup.ShouldProduceFullVTable(method.OwningType))
_graph.AddRoot(_factory.VirtualMethodUse(method), reason);
// Virtual method use is tracked on the slot defining method only.
MethodDesc slotDefiningMethod = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method);
if (!_factory.VTable(slotDefiningMethod.OwningType).HasFixedSlots)
_graph.AddRoot(_factory.VirtualMethodUse(slotDefiningMethod), reason);
if (method.IsAbstract)
{
_graph.AddRoot(_factory.ReflectableMethod(method), reason);
}
}
public void RootModuleMetadata(ModuleDesc module, string reason)
{
_graph.AddRoot(_factory.ModuleMetadata(module), reason);
}
}
}
// Interface under which Compilation is exposed externally.
public interface ICompilation
{
void Compile(string outputFileName, ObjectDumper dumper);
void WriteDependencyLog(string outputFileName);
CompilationResults Compile(string outputFileName, ObjectDumper dumper);
}
public class CompilationResults
{
private readonly DependencyAnalyzerBase<NodeFactory> _graph;
private readonly NodeFactory _factory;
protected ImmutableArray<DependencyNodeCore<NodeFactory>> MarkedNodes
{
get
{
return _graph.MarkedNodeList;
}
}
internal CompilationResults(DependencyAnalyzerBase<NodeFactory> graph, NodeFactory factory)
{
_graph = graph;
_factory = factory;
}
public void WriteDependencyLog(string fileName)
{
using (FileStream dgmlOutput = new FileStream(fileName, FileMode.Create))
{
DgmlWriter.WriteDependencyGraphToStream(dgmlOutput, _graph, _factory);
dgmlOutput.Flush();
}
}
public IEnumerable<MethodDesc> CompiledMethodBodies
{
get
{
foreach (var node in MarkedNodes)
{
if (node is IMethodBodyNode)
yield return ((IMethodBodyNode)node).Method;
}
}
}
public IEnumerable<TypeDesc> ConstructedEETypes
{
get
{
foreach (var node in MarkedNodes)
{
if (node is ConstructedEETypeNode || node is CanonicalEETypeNode)
{
yield return ((IEETypeNode)node).Type;
}
}
}
}
}
}

View File

@@ -22,15 +22,18 @@ namespace ILCompiler
private DependencyTrackingLevel _dependencyTrackingLevel = DependencyTrackingLevel.None;
protected IEnumerable<ICompilationRootProvider> _compilationRoots = Array.Empty<ICompilationRootProvider>();
protected OptimizationMode _optimizationMode = OptimizationMode.None;
protected bool _generateDebugInfo = false;
protected MetadataManager _metadataManager;
protected VTableSliceProvider _vtableSliceProvider = new LazyVTableSliceProvider();
protected DictionaryLayoutProvider _dictionaryLayoutProvider = new LazyDictionaryLayoutProvider();
protected DebugInformationProvider _debugInformationProvider = new DebugInformationProvider();
protected DevirtualizationManager _devirtualizationManager = new DevirtualizationManager();
public CompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler nameMangler)
{
_context = context;
_compilationGroup = compilationGroup;
_nameMangler = nameMangler;
_metadataManager = new EmptyMetadataManager(compilationGroup, context);
_metadataManager = new EmptyMetadataManager(context);
}
public CompilationBuilder UseLogger(Logger logger)
@@ -63,18 +66,35 @@ namespace ILCompiler
return this;
}
public CompilationBuilder UseDebugInfo(bool generateDebugInfo)
public CompilationBuilder UseVTableSliceProvider(VTableSliceProvider provider)
{
_generateDebugInfo = generateDebugInfo;
_vtableSliceProvider = provider;
return this;
}
public CompilationBuilder UseGenericDictionaryLayoutProvider(DictionaryLayoutProvider provider)
{
_dictionaryLayoutProvider = provider;
return this;
}
public CompilationBuilder UseDevirtualizationManager(DevirtualizationManager manager)
{
_devirtualizationManager = manager;
return this;
}
public CompilationBuilder UseDebugInfoProvider(DebugInformationProvider provider)
{
_debugInformationProvider = provider;
return this;
}
public abstract CompilationBuilder UseBackendOptions(IEnumerable<string> options);
protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory)
protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory, IComparer<DependencyNodeCore<NodeFactory>> comparer = null)
{
// TODO: add graph sorter when we go multi-threaded
return _dependencyTrackingLevel.CreateDependencyGraph(factory);
return _dependencyTrackingLevel.CreateDependencyGraph(factory, comparer);
}
public ILScannerBuilder GetILScannerBuilder(CompilationModuleGroup compilationGroup = null)

View File

@@ -12,6 +12,13 @@ using Debug = System.Diagnostics.Debug;
namespace ILCompiler
{
public enum ExportForm
{
None = 0,
ByName = 1,
ByOrdinal = 2,
}
public abstract class CompilationModuleGroup
{
/// <summary>
@@ -30,9 +37,13 @@ namespace ILCompiler
/// </summary>
public abstract bool ContainsType(TypeDesc type);
/// <summary>
/// If true, type dictionary of "type" is in the module to be compiled
/// </summary>
public abstract bool ContainsTypeDictionary(TypeDesc type);
/// <summary>
/// If true, "method" is in the set of input assemblies being compiled
/// </summary>
public abstract bool ContainsMethodBody(MethodDesc method);
public abstract bool ContainsMethodBody(MethodDesc method, bool unboxingStub);
/// <summary>
/// If true, the generic dictionary of "method" is in the set of input assemblies being compiled
/// </summary>
@@ -40,15 +51,19 @@ namespace ILCompiler
/// <summary>
/// If true, "type" is exported by the set of input assemblies being compiled
/// </summary>
public abstract bool ExportsType(TypeDesc type);
public abstract ExportForm GetExportTypeForm(TypeDesc type);
/// <summary>
/// If true, generic dictionary of "type" is exported by the set of input assemblies being compiled
/// </summary>
public abstract ExportForm GetExportTypeFormDictionary(TypeDesc type);
/// <summary>
/// If true, "method" is exported by the set of input assemblies being compiled
/// </summary>
public abstract bool ExportsMethod(MethodDesc method);
public abstract ExportForm GetExportMethodForm(MethodDesc method, bool unboxingStub);
/// <summary>
/// If true, the generic dictionary of "method" is exported by the set of input assemblies being compiled
/// </summary>
public abstract bool ExportsMethodDictionary(MethodDesc method);
public abstract ExportForm GetExportMethodDictionaryForm(MethodDesc method);
/// <summary>
/// If true, all code is compiled into a single module
/// </summary>
@@ -64,6 +79,11 @@ namespace ILCompiler
/// </summary>
public abstract bool ShouldPromoteToFullType(TypeDesc type);
/// <summary>
/// If true, if a type is in the dependency graph, its non-generic methods that can be transformed
/// into code must be.
/// </summary>
public abstract bool PresenceOfEETypeImpliesAllMethodsOnType(TypeDesc type);
/// <summary>
/// If true, the type will not be linked into the same module as the current compilation and therefore
/// accessed through the target platform's import mechanism (ie, Import Address Table on Windows)
/// </summary>
@@ -102,10 +122,10 @@ namespace ILCompiler
public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
{
Debug.Assert(false, "Resolving a TypeRef in the compiler generated assembly?");
Debug.Fail("Resolving a TypeRef in the compiler generated assembly?");
if (throwIfNotFound)
throw new TypeSystemException.TypeLoadException(nameSpace, name, this);
ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
return null;
}

View File

@@ -0,0 +1,282 @@
// 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.Collections.Generic;
using Internal.IL.Stubs;
using Internal.TypeSystem;
using Internal.TypeSystem.Interop;
using ILCompiler.DependencyAnalysis;
using Debug = System.Diagnostics.Debug;
using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
using ReflectionMapBlob = Internal.Runtime.ReflectionMapBlob;
namespace ILCompiler
{
/// <summary>
/// This class is responsible for managing stub methods for interop
/// </summary>
public sealed class CompilerGeneratedInteropStubManager : InteropStubManager
{
internal HashSet<TypeDesc> _delegateMarshalingTypes = new HashSet<TypeDesc>();
private HashSet<TypeDesc> _structMarshallingTypes = new HashSet<TypeDesc>();
public CompilerGeneratedInteropStubManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext, InteropStateManager interopStateManager) :
base(compilationModuleGroup, typeSystemContext, interopStateManager)
{
}
private MethodDesc GetOpenStaticDelegateMarshallingStub(TypeDesc delegateType)
{
var stub = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType);
Debug.Assert(stub != null);
_delegateMarshalingTypes.Add(delegateType);
return stub;
}
private MethodDesc GetClosedDelegateMarshallingStub(TypeDesc delegateType)
{
var stub = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType);
Debug.Assert(stub != null);
_delegateMarshalingTypes.Add(delegateType);
return stub;
}
private MethodDesc GetForwardDelegateCreationStub(TypeDesc delegateType)
{
var stub = InteropStateManager.GetForwardDelegateCreationThunk(delegateType);
Debug.Assert(stub != null);
_delegateMarshalingTypes.Add(delegateType);
return stub;
}
private MethodDesc GetStructMarshallingManagedToNativeStub(TypeDesc structType)
{
MethodDesc stub = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType);
Debug.Assert(stub != null);
_structMarshallingTypes.Add(structType);
return stub;
}
private MethodDesc GetStructMarshallingNativeToManagedStub(TypeDesc structType)
{
MethodDesc stub = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType);
Debug.Assert(stub != null);
_structMarshallingTypes.Add(structType);
return stub;
}
private MethodDesc GetStructMarshallingCleanupStub(TypeDesc structType)
{
MethodDesc stub = InteropStateManager.GetStructMarshallingCleanupThunk(structType);
Debug.Assert(stub != null);
_structMarshallingTypes.Add(structType);
return stub;
}
private TypeDesc GetInlineArrayType(InlineArrayCandidate candidate)
{
TypeDesc inlineArrayType = InteropStateManager.GetInlineArrayType(candidate);
Debug.Assert(inlineArrayType != null);
return inlineArrayType;
}
internal struct DelegateMarshallingThunks
{
public TypeDesc DelegateType;
public MethodDesc OpenStaticDelegateMarshallingThunk;
public MethodDesc ClosedDelegateMarshallingThunk;
public MethodDesc DelegateCreationThunk;
}
internal IEnumerable<DelegateMarshallingThunks> GetDelegateMarshallingThunks()
{
foreach (var delegateType in _delegateMarshalingTypes)
{
yield return
new DelegateMarshallingThunks()
{
DelegateType = delegateType,
OpenStaticDelegateMarshallingThunk = InteropStateManager.GetOpenStaticDelegateMarshallingThunk(delegateType),
ClosedDelegateMarshallingThunk = InteropStateManager.GetClosedDelegateMarshallingThunk(delegateType),
DelegateCreationThunk = InteropStateManager.GetForwardDelegateCreationThunk(delegateType)
};
}
}
internal struct StructMarshallingThunks
{
public TypeDesc StructType;
public NativeStructType NativeStructType;
public MethodDesc MarshallingThunk;
public MethodDesc UnmarshallingThunk;
public MethodDesc CleanupThunk;
}
internal IEnumerable<StructMarshallingThunks> GetStructMarshallingTypes()
{
foreach (var structType in _structMarshallingTypes)
{
yield return
new StructMarshallingThunks()
{
StructType = structType,
NativeStructType = InteropStateManager.GetStructMarshallingNativeType(structType),
MarshallingThunk = InteropStateManager.GetStructMarshallingManagedToNativeThunk(structType),
UnmarshallingThunk = InteropStateManager.GetStructMarshallingNativeToManagedThunk(structType),
CleanupThunk = InteropStateManager.GetStructMarshallingCleanupThunk(structType)
};
}
}
private void AddDependenciesDueToPInvokeStructDelegateField(ref DependencyList dependencies, NodeFactory factory, TypeDesc typeDesc)
{
if (typeDesc is ByRefType)
{
typeDesc = typeDesc.GetParameterType();
}
MetadataType metadataType = typeDesc as MetadataType;
if (metadataType != null)
{
foreach (FieldDesc field in metadataType.GetFields())
{
if (field.IsStatic)
{
continue;
}
TypeDesc fieldType = field.FieldType;
if (fieldType.IsDelegate)
{
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, fieldType);
}
else if (MarshalHelpers.IsStructMarshallingRequired(fieldType))
{
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, fieldType);
}
}
}
}
public override void AddDependeciesDueToPInvoke(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
{
if (method.IsPInvoke)
{
dependencies = dependencies ?? new DependencyList();
MethodSignature methodSig = method.Signature;
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig.ReturnType);
// struct may contain delegate fields, hence we need to add dependencies for it
if (MarshalHelpers.IsStructMarshallingRequired(methodSig.ReturnType))
{
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig.ReturnType);
}
for (int i = 0; i < methodSig.Length; i++)
{
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, methodSig[i]);
if (MarshalHelpers.IsStructMarshallingRequired(methodSig[i]))
{
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, methodSig[i]);
}
}
}
if (method.HasInstantiation)
{
dependencies = dependencies ?? new DependencyList();
AddMarshalAPIsGenericDependencies(ref dependencies, factory, method);
}
}
public override void AddInterestingInteropConstructedTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
if (type.IsDelegate)
{
var delegateType = (MetadataType)type;
if (delegateType.HasCustomAttribute("System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"))
{
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, delegateType);
}
}
}
/// <summary>
/// For Marshal generic APIs(eg. Marshal.StructureToPtr<T>, GetFunctionPointerForDelegate) we add
/// the generic parameter as dependencies so that we can generate runtime data for them
/// </summary>
public override void AddMarshalAPIsGenericDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
{
Debug.Assert(method.HasInstantiation);
TypeDesc owningType = method.OwningType;
MetadataType metadataType = owningType as MetadataType;
if (metadataType != null && metadataType.Module == _interopModule)
{
if (metadataType.Name == "Marshal" && metadataType.Namespace == "System.Runtime.InteropServices")
{
string methodName = method.Name;
if (methodName == "GetFunctionPointerForDelegate" ||
methodName == "GetDelegateForFunctionPointer" ||
methodName == "PtrToStructure" ||
methodName == "StructureToPtr" ||
methodName == "SizeOf" ||
methodName == "OffsetOf")
{
foreach (TypeDesc type in method.Instantiation)
{
AddDependenciesDueToPInvokeDelegate(ref dependencies, factory, type);
AddDependenciesDueToPInvokeStruct(ref dependencies, factory, type);
}
}
}
}
}
private void AddDependenciesDueToPInvokeDelegate(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
if (type.IsDelegate)
{
dependencies.Add(factory.NecessaryTypeSymbol(type), "Delegate Marshalling Stub");
dependencies.Add(factory.MethodEntrypoint(GetOpenStaticDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
dependencies.Add(factory.MethodEntrypoint(GetClosedDelegateMarshallingStub(type)), "Delegate Marshalling Stub");
dependencies.Add(factory.MethodEntrypoint(GetForwardDelegateCreationStub(type)), "Delegate Marshalling Stub");
}
}
private void AddDependenciesDueToPInvokeStruct(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
if (MarshalHelpers.IsStructMarshallingRequired(type))
{
dependencies.Add(factory.NecessaryTypeSymbol(type), "Struct Marshalling Stub");
var stub = (StructMarshallingThunk)GetStructMarshallingManagedToNativeStub(type);
dependencies.Add(factory.MethodEntrypoint(stub), "Struct Marshalling stub");
dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingNativeToManagedStub(type)), "Struct Marshalling stub");
dependencies.Add(factory.MethodEntrypoint(GetStructMarshallingCleanupStub(type)), "Struct Marshalling stub");
AddDependenciesDueToPInvokeStructDelegateField(ref dependencies, factory, type);
}
}
public override void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode)
{
var delegateMapNode = new DelegateMarshallingStubMapNode(commonFixupsTableNode);
header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode, delegateMapNode, delegateMapNode.EndSymbol);
var structMapNode = new StructMarshallingStubMapNode(commonFixupsTableNode);
header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode, structMapNode, structMapNode.EndSymbol);
}
}
}

View File

@@ -1,284 +0,0 @@
// 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.IO;
using System.Collections.Generic;
using System.Text;
using Internal.IL.Stubs;
using Internal.TypeSystem;
using Internal.Metadata.NativeFormat.Writer;
using ILCompiler.Metadata;
using ILCompiler.DependencyAnalysis;
using Debug = System.Diagnostics.Debug;
using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore<ILCompiler.DependencyAnalysis.NodeFactory>.DependencyList;
namespace ILCompiler
{
/// <summary>
/// This class is responsible for managing native metadata to be emitted into the compiled
/// module. It applies a policy that every type/method emitted shall be reflectable.
/// </summary>
public sealed class CompilerGeneratedMetadataManager : MetadataManager
{
private readonly string _metadataLogFile;
private Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks;
public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext, string logFile)
: base(group, typeSystemContext, new BlockedInternalsBlockingPolicy())
{
_metadataLogFile = logFile;
if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext))
{
_dynamicInvokeThunks = new Dictionary<DynamicInvokeMethodSignature, MethodDesc>();
}
}
public override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method)
{
return (GetMetadataCategory(method) & MetadataCategory.Description) != 0;
}
public override bool WillUseMetadataTokenToReferenceField(FieldDesc field)
{
return (GetMetadataCategory(field) & MetadataCategory.Description) != 0;
}
protected override MetadataCategory GetMetadataCategory(FieldDesc field)
{
MetadataCategory category = 0;
if (!IsReflectionBlocked(field))
{
category = MetadataCategory.RuntimeMapping;
if (_compilationModuleGroup.ContainsType(field.GetTypicalFieldDefinition().OwningType))
category |= MetadataCategory.Description;
}
return category;
}
protected override MetadataCategory GetMetadataCategory(MethodDesc method)
{
MetadataCategory category = 0;
if (!IsReflectionBlocked(method))
{
category = MetadataCategory.RuntimeMapping;
if (_compilationModuleGroup.ContainsType(method.GetTypicalMethodDefinition().OwningType))
category |= MetadataCategory.Description;
}
return category;
}
protected override MetadataCategory GetMetadataCategory(TypeDesc type)
{
MetadataCategory category = 0;
if (!IsReflectionBlocked(type))
{
category = MetadataCategory.RuntimeMapping;
if (_compilationModuleGroup.ContainsType(type.GetTypeDefinition()))
category |= MetadataCategory.Description;
}
return category;
}
protected override void ComputeMetadata(NodeFactory factory,
out byte[] metadataBlob,
out List<MetadataMapping<MetadataType>> typeMappings,
out List<MetadataMapping<MethodDesc>> methodMappings,
out List<MetadataMapping<FieldDesc>> fieldMappings)
{
var transformed = MetadataTransform.Run(new GeneratedTypesAndCodeMetadataPolicy(_blockingPolicy, factory), GetCompilationModulesWithMetadata());
// TODO: DeveloperExperienceMode: Use transformed.Transform.HandleType() to generate
// TypeReference records for _typeDefinitionsGenerated that don't have metadata.
// (To be used in MissingMetadataException messages)
// Generate metadata blob
var writer = new MetadataWriter();
writer.ScopeDefinitions.AddRange(transformed.Scopes);
var ms = new MemoryStream();
// .NET metadata is UTF-16 and UTF-16 contains code points that don't translate to UTF-8.
var noThrowUtf8Encoding = new UTF8Encoding(false, false);
using (var logWriter = _metadataLogFile != null ? new StreamWriter(File.Open(_metadataLogFile, FileMode.Create, FileAccess.Write, FileShare.Read), noThrowUtf8Encoding) : null)
{
writer.LogWriter = logWriter;
writer.Write(ms);
}
metadataBlob = ms.ToArray();
typeMappings = new List<MetadataMapping<MetadataType>>();
methodMappings = new List<MetadataMapping<MethodDesc>>();
fieldMappings = new List<MetadataMapping<FieldDesc>>();
// Generate type definition mappings
foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
{
MetadataType definition = type.IsTypeDefinition ? type as MetadataType : null;
if (definition == null)
continue;
MetadataRecord record = transformed.GetTransformedTypeDefinition(definition);
// Reflection requires that we maintain type identity. Even if we only generated a TypeReference record,
// if there is an EEType for it, we also need a mapping table entry for it.
if (record == null)
record = transformed.GetTransformedTypeReference(definition);
if (record != null)
typeMappings.Add(new MetadataMapping<MetadataType>(definition, writer.GetRecordHandle(record)));
}
foreach (var method in GetCompiledMethods())
{
if (method.IsCanonicalMethod(CanonicalFormKind.Specific))
{
// Canonical methods are not interesting.
continue;
}
if (IsReflectionBlocked(method.Instantiation) || IsReflectionBlocked(method.OwningType.Instantiation))
continue;
MetadataRecord record = transformed.GetTransformedMethodDefinition(method.GetTypicalMethodDefinition());
if (record != null)
methodMappings.Add(new MetadataMapping<MethodDesc>(method, writer.GetRecordHandle(record)));
}
foreach (var eetypeGenerated in GetTypesWithEETypes())
{
if (eetypeGenerated.IsGenericDefinition)
continue;
if (eetypeGenerated.HasInstantiation)
{
// Collapsing of field map entries based on canonicalization, to avoid redundant equivalent entries
TypeDesc canonicalType = eetypeGenerated.ConvertToCanonForm(CanonicalFormKind.Specific);
if (canonicalType != eetypeGenerated && TypeGeneratesEEType(canonicalType))
continue;
}
foreach (FieldDesc field in eetypeGenerated.GetFields())
{
if (IsReflectionBlocked(field.OwningType.Instantiation))
continue;
Field record = transformed.GetTransformedFieldDefinition(field.GetTypicalFieldDefinition());
if (record != null)
fieldMappings.Add(new MetadataMapping<FieldDesc>(field, writer.GetRecordHandle(record)));
}
}
}
/// <summary>
/// Is there a reflection invoke stub for a method that is invokable?
/// </summary>
public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
{
Debug.Assert(IsReflectionInvokable(method));
if (_dynamicInvokeThunks == null)
return false;
// Place an upper limit on how many parameters a method can have to still get a static stub.
// From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations
// in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations.
// We don't have such limitations here, but it's a nice round number.
// Reflection invoke will still work, but will go through the calling convention converter.
return method.Signature.Length <= 256;
}
/// <summary>
/// Gets a stub that can be used to reflection-invoke a method with a given signature.
/// </summary>
public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
{
TypeSystemContext context = method.Context;
var sig = method.Signature;
// Get a generic method that can be used to invoke method with this shape.
MethodDesc thunk;
var lookupSig = new DynamicInvokeMethodSignature(sig);
if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
{
thunk = new DynamicInvokeMethodThunk(_compilationModuleGroup.GeneratedAssembly.GetGlobalModuleType(), lookupSig);
_dynamicInvokeThunks.Add(lookupSig, thunk);
}
return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method);
}
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
{
dependencies = dependencies ?? new DependencyList();
dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method");
}
protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type)
{
TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type");
}
private struct GeneratedTypesAndCodeMetadataPolicy : IMetadataPolicy
{
private readonly MetadataBlockingPolicy _blockingPolicy;
private readonly NodeFactory _factory;
private readonly ExplicitScopeAssemblyPolicyMixin _explicitScopeMixin;
public GeneratedTypesAndCodeMetadataPolicy(MetadataBlockingPolicy blockingPolicy, NodeFactory factory)
{
_blockingPolicy = blockingPolicy;
_factory = factory;
_explicitScopeMixin = new ExplicitScopeAssemblyPolicyMixin();
}
public bool GeneratesMetadata(FieldDesc fieldDef)
{
return _factory.FieldMetadata(fieldDef).Marked;
}
public bool GeneratesMetadata(MethodDesc methodDef)
{
return _factory.MethodMetadata(methodDef).Marked;
}
public bool GeneratesMetadata(MetadataType typeDef)
{
return _factory.TypeMetadata(typeDef).Marked;
}
public bool IsBlocked(MetadataType typeDef)
{
return _blockingPolicy.IsBlocked(typeDef);
}
public bool IsBlocked(MethodDesc methodDef)
{
return _blockingPolicy.IsBlocked(methodDef);
}
public ModuleDesc GetModuleOfType(MetadataType typeDef)
{
return _explicitScopeMixin.GetModuleOfType(typeDef);
}
}
}
}

View File

@@ -77,7 +77,8 @@ namespace ILCompiler
return TypeFlags.Class |
TypeFlags.HasGenericVarianceComputed |
TypeFlags.HasStaticConstructorComputed |
TypeFlags.HasFinalizerComputed;
TypeFlags.HasFinalizerComputed |
TypeFlags.IsByRefLikeComputed;
}
public override ClassLayoutMetadata GetClassLayout()

View File

@@ -89,6 +89,40 @@ namespace ILCompiler
return thunk;
}
public MethodDesc GetUnboxingThunk(MethodDesc targetMethod, ModuleDesc ownerModuleOfThunk)
{
TypeDesc owningType = targetMethod.OwningType;
Debug.Assert(owningType.IsValueType);
var owningTypeDefinition = (MetadataType)owningType.GetTypeDefinition();
// Get a reference type that has the same layout as the boxed valuetype.
var typeKey = new BoxedValuetypeHashtableKey(owningTypeDefinition, ownerModuleOfThunk);
BoxedValueType boxedTypeDefinition = _boxedValuetypeHashtable.GetOrCreateValue(typeKey);
// Get a method on the reference type with the same signature as the target method (but different
// calling convention, since 'this' will be a reference type).
var targetMethodDefinition = targetMethod.GetTypicalMethodDefinition();
var methodKey = new UnboxingThunkHashtableKey(targetMethodDefinition, boxedTypeDefinition);
UnboxingThunk thunkDefinition = _nonGenericUnboxingThunkHashtable.GetOrCreateValue(methodKey);
// Find the thunk on the instantiated version of the reference type.
if (owningType != owningTypeDefinition)
{
InstantiatedType boxedType = boxedTypeDefinition.MakeInstantiatedType(owningType.Instantiation);
MethodDesc thunk = GetMethodForInstantiatedType(thunkDefinition, boxedType);
//TODO: this might be triggered by a struct that implements an interface with a generic method
Debug.Assert(!thunk.HasInstantiation);
return thunk;
}
else
{
//TODO: this might be triggered by a struct that implements an interface with a generic method
Debug.Assert(!thunkDefinition.HasInstantiation);
return thunkDefinition;
}
}
/// <summary>
/// Returns true of <paramref name="method"/> is a standin method for unboxing thunk target.
/// </summary>
@@ -184,7 +218,34 @@ namespace ILCompiler
}
}
private UnboxingThunkHashtable _unboxingThunkHashtable = new UnboxingThunkHashtable();
private class NonGenericUnboxingThunkHashtable : LockFreeReaderHashtable<UnboxingThunkHashtableKey, UnboxingThunk>
{
protected override int GetKeyHashCode(UnboxingThunkHashtableKey key)
{
return key.TargetMethod.GetHashCode();
}
protected override int GetValueHashCode(UnboxingThunk value)
{
return value.TargetMethod.GetHashCode();
}
protected override bool CompareKeyToValue(UnboxingThunkHashtableKey key, UnboxingThunk value)
{
return Object.ReferenceEquals(key.TargetMethod, value.TargetMethod) &&
Object.ReferenceEquals(key.OwningType, value.OwningType);
}
protected override bool CompareValueToValue(UnboxingThunk value1, UnboxingThunk value2)
{
return Object.ReferenceEquals(value1.TargetMethod, value2.TargetMethod) &&
Object.ReferenceEquals(value1.OwningType, value2.OwningType);
}
protected override UnboxingThunk CreateValueFromKey(UnboxingThunkHashtableKey key)
{
return new UnboxingThunk(key.OwningType, key.TargetMethod);
}
}
private NonGenericUnboxingThunkHashtable _nonGenericUnboxingThunkHashtable = new NonGenericUnboxingThunkHashtable();
/// <summary>
/// A type with an identical layout to the layout of a boxed value type.
@@ -210,6 +271,7 @@ namespace ILCompiler
public override bool IsSequentialLayout => true;
public override bool IsBeforeFieldInit => false;
public override MetadataType MetadataBaseType => (MetadataType)Context.GetWellKnownType(WellKnownType.Object);
public override DefType BaseType => MetadataBaseType;
public override bool IsSealed => true;
public override bool IsAbstract => false;
public override DefType ContainingType => null;
@@ -248,11 +310,6 @@ namespace ILCompiler
return hashCodeBuilder.ToHashCode();
}
public override string ToString()
{
return "Boxed " + Module.ToString() + ValueTypeRepresented.ToString();
}
protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
{
TypeFlags flags = 0;
@@ -268,6 +325,7 @@ namespace ILCompiler
}
flags |= TypeFlags.HasFinalizerComputed;
flags |= TypeFlags.IsByRefLikeComputed;
return flags;
}
@@ -414,6 +472,67 @@ namespace ILCompiler
}
}
/// <summary>
/// Represents a thunk to call instance method on boxed valuetypes.
/// </summary>
private partial class UnboxingThunk : ILStubMethod
{
private MethodDesc _targetMethod;
private BoxedValueType _owningType;
public UnboxingThunk(BoxedValueType owningType, MethodDesc targetMethod)
{
Debug.Assert(targetMethod.OwningType.IsValueType);
Debug.Assert(!targetMethod.Signature.IsStatic);
_owningType = owningType;
_targetMethod = targetMethod;
}
public override TypeSystemContext Context => _targetMethod.Context;
public override TypeDesc OwningType => _owningType;
public override MethodSignature Signature => _targetMethod.Signature;
public MethodDesc TargetMethod => _targetMethod;
public override string Name
{
get
{
return _targetMethod.Name + "_Unbox";
}
}
public override MethodIL EmitIL()
{
// Generate the unboxing stub. This loosely corresponds to following C#:
// return BoxedValue.InstanceMethod([rest of parameters])
ILEmitter emit = new ILEmitter();
ILCodeStream codeStream = emit.NewCodeStream();
FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen();
// unbox to get a pointer to the value type
codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField));
// Load rest of the arguments
for (int i = 0; i < _targetMethod.Signature.Length; i++)
{
codeStream.EmitLdArg(i + 1);
}
// Call an instance method on the target valuetype
codeStream.Emit(ILOpcode.call, emit.NewToken(_targetMethod.InstantiateAsOpen()));
codeStream.Emit(ILOpcode.ret);
return emit.Link(this);
}
}
/// <summary>
/// Represents an instance method on a generic valuetype with an explicit instantiation parameter in the
/// signature. This is so that we can refer to the parameter from IL. References to this method will

View File

@@ -40,6 +40,17 @@ namespace ILCompiler
}
}
partial class UnboxingThunk
{
protected override int ClassCode => 446545583;
protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
var otherMethod = (UnboxingThunk)other;
return comparer.Compare(_targetMethod, otherMethod._targetMethod);
}
}
partial class ValueTypeInstanceMethodWithHiddenParameter
{
protected override int ClassCode => 2131875345;

View File

@@ -22,10 +22,13 @@ namespace ILCompiler
{
private MetadataFieldLayoutAlgorithm _metadataFieldLayoutAlgorithm = new CompilerMetadataFieldLayoutAlgorithm();
private RuntimeDeterminedFieldLayoutAlgorithm _runtimeDeterminedFieldLayoutAlgorithm = new RuntimeDeterminedFieldLayoutAlgorithm();
private VectorOfTFieldLayoutAlgorithm _vectorOfTFieldLayoutAlgorithm;
private MetadataRuntimeInterfacesAlgorithm _metadataRuntimeInterfacesAlgorithm = new MetadataRuntimeInterfacesAlgorithm();
private ArrayOfTRuntimeInterfacesAlgorithm _arrayOfTRuntimeInterfacesAlgorithm;
private MetadataVirtualMethodAlgorithm _virtualMethodAlgorithm = new MetadataVirtualMethodAlgorithm();
private SimdHelper _simdHelper;
private TypeDesc[] _arrayOfTInterfaces;
private MetadataStringDecoder _metadataStringDecoder;
@@ -59,7 +62,7 @@ namespace ILCompiler
}
protected override ModuleData CreateValueFromKey(EcmaModule key)
{
Debug.Assert(false, "CreateValueFromKey not supported");
Debug.Fail("CreateValueFromKey not supported");
return null;
}
}
@@ -87,7 +90,7 @@ namespace ILCompiler
}
protected override ModuleData CreateValueFromKey(string key)
{
Debug.Assert(false, "CreateValueFromKey not supported");
Debug.Fail("CreateValueFromKey not supported");
return null;
}
}
@@ -99,6 +102,8 @@ namespace ILCompiler
: base(details)
{
_genericsMode = genericsMode;
_vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_metadataFieldLayoutAlgorithm);
}
public IReadOnlyDictionary<string, string> InputFilePaths
@@ -128,7 +133,7 @@ namespace ILCompiler
return GetModuleForSimpleName(name.Name, throwIfNotFound);
}
public EcmaModule GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
public ModuleDesc GetModuleForSimpleName(string simpleName, bool throwIfNotFound = true)
{
ModuleData existing;
if (_simpleNameHashtable.TryGetValue(simpleName, out existing))
@@ -139,19 +144,33 @@ namespace ILCompiler
{
if (!ReferenceFilePaths.TryGetValue(simpleName, out filePath))
{
// We allow the CanonTypesModule to not be an EcmaModule.
if (((IAssemblyDesc)CanonTypesModule).GetName().Name == simpleName)
return CanonTypesModule;
// TODO: the exception is wrong for two reasons: for one, this should be assembly full name, not simple name.
// The other reason is that on CoreCLR, the exception also captures the reason. We should be passing two
// string IDs. This makes this rather annoying.
if (throwIfNotFound)
throw new TypeSystemException.FileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
ThrowHelper.ThrowFileNotFoundException(ExceptionStringID.FileLoadErrorGeneric, simpleName);
return null;
}
}
return AddModule(filePath, simpleName);
return AddModule(filePath, simpleName, true);
}
public EcmaModule GetModuleFromPath(string filePath)
{
return GetOrAddModuleFromPath(filePath, true);
}
public EcmaModule GetMetadataOnlyModuleFromPath(string filePath)
{
return GetOrAddModuleFromPath(filePath, false);
}
private EcmaModule GetOrAddModuleFromPath(string filePath, bool useForBinding)
{
// This method is not expected to be called frequently. Linear search is acceptable.
foreach (var entry in ModuleHashtable.Enumerator.Get(_moduleHashtable))
@@ -160,10 +179,10 @@ namespace ILCompiler
return entry.Module;
}
return AddModule(filePath, null);
return AddModule(filePath, null, useForBinding);
}
private static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAccessor mappedViewAccessor)
public static unsafe PEReader OpenPEFile(string filePath, out MemoryMappedViewAccessor mappedViewAccessor)
{
// System.Reflection.Metadata has heuristic that tries to save virtual address space. This heuristic does not work
// well for us since it can make IL access very slow (call to OS for each method IL query). We will map the file
@@ -201,7 +220,7 @@ namespace ILCompiler
}
}
private EcmaModule AddModule(string filePath, string expectedSimpleName)
private EcmaModule AddModule(string filePath, string expectedSimpleName, bool useForBinding)
{
MemoryMappedViewAccessor mappedViewAccessor = null;
PdbSymbolReader pdbReader = null;
@@ -228,12 +247,15 @@ namespace ILCompiler
lock (this)
{
ModuleData actualModuleData = _simpleNameHashtable.AddOrGetExisting(moduleData);
if (actualModuleData != moduleData)
if (useForBinding)
{
if (actualModuleData.FilePath != filePath)
throw new FileNotFoundException("Module with same simple name already exists " + filePath);
return actualModuleData.Module;
ModuleData actualModuleData = _simpleNameHashtable.AddOrGetExisting(moduleData);
if (actualModuleData != moduleData)
{
if (actualModuleData.FilePath != filePath)
throw new FileNotFoundException("Module with same simple name already exists " + filePath);
return actualModuleData.Module;
}
}
mappedViewAccessor = null; // Ownership has been transfered
pdbReader = null; // Ownership has been transferred
@@ -258,6 +280,8 @@ namespace ILCompiler
return UniversalCanonLayoutAlgorithm.Instance;
else if (type.IsRuntimeDeterminedType)
return _runtimeDeterminedFieldLayoutAlgorithm;
else if (_simdHelper.IsVectorOfT(type))
return _vectorOfTFieldLayoutAlgorithm;
else
return _metadataFieldLayoutAlgorithm;
}
@@ -325,19 +349,21 @@ namespace ILCompiler
return type.GetMethods();
}
private IEnumerable<MethodDesc> GetAllMethodsForDelegate(TypeDesc type)
protected virtual IEnumerable<MethodDesc> GetAllMethodsForDelegate(TypeDesc type)
{
// Inject the synthetic GetThunk virtual override
// Inject the synthetic methods that support the implementation of the delegate.
InstantiatedType instantiatedType = type as InstantiatedType;
if (instantiatedType != null)
{
DelegateInfo info = GetDelegateInfo(type.GetTypeDefinition());
yield return GetMethodForInstantiatedType(info.GetThunkMethod, instantiatedType);
foreach (MethodDesc syntheticMethod in info.Methods)
yield return GetMethodForInstantiatedType(syntheticMethod, instantiatedType);
}
else
{
DelegateInfo info = GetDelegateInfo(type);
yield return info.GetThunkMethod;
foreach (MethodDesc syntheticMethod in info.Methods)
yield return syntheticMethod;
}
// Append all the methods defined in metadata

View File

@@ -165,6 +165,7 @@ namespace ILCompiler
private string EnterNameScopeSequence => _mangleForCplusPlus ? "_A_" : "<";
private string ExitNameScopeSequence => _mangleForCplusPlus ? "_V_" : ">";
private string DelimitNameScopeSequence => _mangleForCplusPlus? "_C_" : ",";
protected string NestMangledName(string name)
{
@@ -275,17 +276,15 @@ namespace ILCompiler
switch (type.Category)
{
case TypeFlags.Array:
mangledName = "__MDArray" +
EnterNameScopeSequence +
GetMangledTypeName(((ArrayType)type).ElementType) +
DelimitNameScopeSequence +
((ArrayType)type).Rank.ToStringInvariant() +
ExitNameScopeSequence;
break;
case TypeFlags.SzArray:
mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__";
if (type.IsMdArray)
{
mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant());
}
else
{
mangledName += NestMangledName("Array");
}
mangledName = "__Array" + NestMangledName(GetMangledTypeName(((ArrayType)type).ElementType));
break;
case TypeFlags.ByRef:
mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef");

View File

@@ -0,0 +1,30 @@
// 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 Internal.IL;
namespace ILCompiler
{
/// <summary>
/// Provides debug information by delegating to the <see cref="MethodIL"/>.
/// </summary>
public class DebugInformationProvider
{
public virtual MethodDebugInformation GetDebugInfo(MethodIL methodIL)
{
return methodIL.GetDebugInfo();
}
}
/// <summary>
/// Provides empty debug information.
/// </summary>
public sealed class NullDebugInformationProvider : DebugInformationProvider
{
public override MethodDebugInformation GetDebugInfo(MethodIL methodIL)
{
return MethodDebugInformation.None;
}
}
}

View File

@@ -96,7 +96,7 @@ namespace ILCompiler
return factory.GenericLookup.MethodEntry(TargetMethod, TargetMethodIsUnboxingThunk);
case TargetKind.InterfaceDispatch:
return factory.GenericLookup.VirtualMethodAddress(TargetMethod);
return factory.GenericLookup.VirtualDispatchCell(TargetMethod);
case TargetKind.MethodHandle:
return factory.GenericLookup.MethodHandle(TargetMethod);
@@ -129,7 +129,7 @@ namespace ILCompiler
return factory.RuntimeMethodHandle(TargetMethod);
case TargetKind.VTableLookup:
Debug.Assert(false, "Need to do runtime lookup");
Debug.Fail("Need to do runtime lookup");
return null;
default:
@@ -313,5 +313,33 @@ namespace ILCompiler
{
return Constructor.GetHashCode() ^ TargetMethod.GetHashCode();
}
#if !SUPPORT_JIT
internal int CompareTo(DelegateCreationInfo other, TypeSystemComparer comparer)
{
var compare = _targetKind - other._targetKind;
if (compare != 0)
return compare;
compare = comparer.Compare(TargetMethod, other.TargetMethod);
if (compare != 0)
return compare;
compare = comparer.Compare(Constructor.Method, other.Constructor.Method);
if (compare != 0)
return compare;
if (Thunk == other.Thunk)
return 0;
if (Thunk == null)
return -1;
if (other.Thunk == null)
return 1;
return comparer.Compare(Thunk.Method, other.Thunk.Method);
}
#endif
}
}

View File

@@ -36,6 +36,7 @@ namespace ILCompiler.DependencyAnalysis
public override ObjectNodeSection Section => _externalReferences.Section;
public override bool StaticDependenciesAreComputed => true;
public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => !factory.MetadataManager.SupportsReflection;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
@@ -51,7 +52,7 @@ namespace ILCompiler.DependencyAnalysis
Section hashTableSection = writer.NewSection();
hashTableSection.Place(typeMapHashTable);
foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
{
if (!type.IsSzArray)
continue;
@@ -61,8 +62,8 @@ namespace ILCompiler.DependencyAnalysis
if (!arrayType.ElementType.IsValueType)
continue;
// Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);
// Look at the constructed type symbol. If a constructed type wasn't emitted, then the array map entry isn't valid for use
IEETypeNode arrayTypeSymbol = factory.ConstructedTypeSymbol(arrayType);
Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));
@@ -76,5 +77,8 @@ namespace ILCompiler.DependencyAnalysis
return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol });
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayMapNode;
}
}

View File

@@ -11,30 +11,28 @@ using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
public interface IHasStartSymbol
{
ObjectAndOffsetSymbolNode StartSymbol { get; }
}
/// <summary>
/// Represents an array of <typeparamref name="TEmbedded"/> nodes. The contents of this node will be emitted
/// by placing a starting symbol, followed by contents of <typeparamref name="TEmbedded"/> nodes (optionally
/// sorted using provided comparer), followed by ending symbol.
/// </summary>
public class ArrayOfEmbeddedDataNode<TEmbedded> : ObjectNode
public class ArrayOfEmbeddedDataNode<TEmbedded> : EmbeddedDataContainerNode, IHasStartSymbol
where TEmbedded : EmbeddedObjectNode
{
private HashSet<TEmbedded> _nestedNodes = new HashSet<TEmbedded>();
private List<TEmbedded> _nestedNodesList = new List<TEmbedded>();
private ObjectAndOffsetSymbolNode _startSymbol;
private ObjectAndOffsetSymbolNode _endSymbol;
private IComparer<TEmbedded> _sorter;
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter)
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter) : base(startSymbolMangledName, endSymbolMangledName)
{
_startSymbol = new ObjectAndOffsetSymbolNode(this, 0, startSymbolMangledName, true);
_endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true);
_sorter = nodeSorter;
}
public ObjectAndOffsetSymbolNode StartSymbol => _startSymbol;
public ObjectAndOffsetSymbolNode EndSymbol => _endSymbol;
public void AddEmbeddedObject(TEmbedded symbol)
{
lock (_nestedNodes)
@@ -43,16 +41,11 @@ namespace ILCompiler.DependencyAnalysis
{
_nestedNodesList.Add(symbol);
}
symbol.ContainingNode = this;
}
}
public int IndexOfEmbeddedObject(TEmbedded symbol)
{
Debug.Assert(_sorter == null);
return _nestedNodesList.IndexOf(symbol);
}
protected override string GetName(NodeFactory factory) => $"Region {_startSymbol.GetMangledName(factory.NameMangler)}";
protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}";
public override ObjectNodeSection Section => ObjectNodeSection.DataSection;
public override bool IsShareable => false;
@@ -63,10 +56,14 @@ namespace ILCompiler.DependencyAnalysis
protected virtual void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly)
{
int index = 0;
foreach (TEmbedded node in NodesList)
{
if (!relocsOnly)
{
node.InitializeOffsetFromBeginningOfArray(builder.CountBytes);
node.InitializeIndexFromBeginningOfArray(index++);
}
node.EncodeData(ref builder, factory, relocsOnly);
if (node is ISymbolDefinitionNode)
@@ -84,12 +81,12 @@ namespace ILCompiler.DependencyAnalysis
if (_sorter != null)
_nestedNodesList.Sort(_sorter);
builder.AddSymbol(_startSymbol);
builder.AddSymbol(StartSymbol);
GetElementDataForNodes(ref builder, factory, relocsOnly);
_endSymbol.SetSymbolOffset(builder.CountBytes);
builder.AddSymbol(_endSymbol);
EndSymbol.SetSymbolOffset(builder.CountBytes);
builder.AddSymbol(EndSymbol);
ObjectData objData = builder.ToObjectData();
return objData;
@@ -108,15 +105,9 @@ namespace ILCompiler.DependencyAnalysis
return dependencies;
}
}
// TODO: delete this once we review each use of this and put it on the generic plan with the
// right element type
public class ArrayOfEmbeddedDataNode : ArrayOfEmbeddedDataNode<EmbeddedObjectNode>
{
public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<EmbeddedObjectNode> nodeSorter)
: base(startSymbolMangledName, endSymbolMangledName, nodeSorter)
{
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode;
}
}

View File

@@ -14,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis
/// of node each pointer within the vector points to.
/// </summary>
public sealed class ArrayOfEmbeddedPointersNode<TTarget> : ArrayOfEmbeddedDataNode<EmbeddedPointerIndirectionNode<TTarget>>
where TTarget : ISymbolNode
where TTarget : ISortableSymbolNode
{
private int _nextId;
private string _startSymbolMangledName;
@@ -44,16 +44,15 @@ namespace ILCompiler.DependencyAnalysis
return new EmbeddedPointerIndirectionWithSymbolNode(this, target, GetNextId());
}
public EmbeddedObjectNode NewNodeWithSymbol(TTarget target, OnMarkedDelegate callback)
{
return new EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(this, target, GetNextId(), callback);
}
int GetNextId()
{
return System.Threading.Interlocked.Increment(ref _nextId);
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedPointersNode;
private class PointerIndirectionNodeComparer : IComparer<EmbeddedPointerIndirectionNode<TTarget>>
{
private IComparer<TTarget> _innerComparer;
@@ -96,6 +95,8 @@ namespace ILCompiler.DependencyAnalysis
new DependencyListEntry(_parentNode, "Pointer region")
};
}
protected internal override int ClassCode => -66002498;
}
private class EmbeddedPointerIndirectionWithSymbolNode : SimpleEmbeddedPointerIndirectionNode, ISymbolDefinitionNode
@@ -113,27 +114,10 @@ namespace ILCompiler.DependencyAnalysis
int ISymbolDefinitionNode.Offset => OffsetFromBeginningOfArray;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
sb.Append(nameMangler.CompilationUnitPrefix).Append(_parentNode._startSymbolMangledName).Append("_").Append(_id.ToStringInvariant());
}
}
private class EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode : EmbeddedPointerIndirectionWithSymbolNode
{
private OnMarkedDelegate _onMarkedCallback;
public EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(ArrayOfEmbeddedPointersNode<TTarget> futureParent, TTarget target, int id, OnMarkedDelegate onMarkedCallback)
: base(futureParent, target, id)
{
_onMarkedCallback = onMarkedCallback;
}
protected override void OnMarked(NodeFactory factory)
{
base.OnMarked(factory);
_onMarkedCallback(this);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More